#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""P0 回归 v2：先把 state.data 加载到位，再逐 Tab 切换。

v1 的失败原因已查明：`render()` 开头有 `if (state.loading) { main.innerHTML = renderSkeleton(); return; }`，
我没调 `loadData()`，于是每个 Tab 都渲染同一张骨架图 → 文本全等 14838，属探针问题非产品问题。
"""
import io
import json
import sys
from playwright.sync_api import sync_playwright

W = '/Users/liuxinyuan/Desktop/Hermes输出-工作类'
BASE = 'http://127.0.0.1:8765/'
USER = '刘新元'
KEY = 'bior_sw_todos_v2_' + USER
seed = json.load(io.open(W + '/数据/todos.json', encoding='utf-8'))['users'][USER]

ok = True
def chk(label, cond, detail=''):
    global ok
    print('  %s %-32s %s' % ('✅' if cond else '❌', label, detail))
    if not cond:
        ok = False

with sync_playwright() as p:
    br = p.chromium.launch(channel='chrome', headless=True)
    pg = br.new_page(viewport={'width': 1500, 'height': 1000})
    errs = []
    pg.on('pageerror', lambda e: errs.append(str(e)))
    pg.on('dialog', lambda d: d.accept())

    pg.goto(BASE, wait_until='domcontentloaded')
    pg.evaluate("""([u, k, seed]) => {
        localStorage.setItem('bior_auth_token', 'preview-only-token');
        localStorage.setItem('bior_sw_user_v2', JSON.stringify({name:u, role:'admin', dept:'营销中心', line:'diag', open_id:'ou_preview_only'}));
        localStorage.setItem(k, JSON.stringify(seed));
    }""", [USER, KEY, seed])
    pg.goto(BASE + '工具/index.html', wait_until='load')
    pg.wait_for_timeout(2500)
    pg.evaluate("""([u]) => {
        window.state = window.state || {};
        window.state.user = {name:u, role:'admin', dept:'营销中心', line:'diag', open_id:'ou_preview_only'};
        window.__push = 0; pushTodos = function(){ window.__push++; };
        if (typeof showApp === 'function') showApp();
    }""", [USER])
    pg.wait_for_timeout(800)
    pg.evaluate("() => { if (typeof loadData === 'function') loadData(); }")

    keys, state = 0, {}
    for _ in range(24):
        pg.wait_for_timeout(1000)
        state = pg.evaluate("() => ({loading: state.loading, error: state.error || '', n: Object.keys(state.data||{}).length})")
        keys = state['n']
        if keys >= 8 and not state['loading']:
            break
    print('state.data 键数=%d loading=%s error=%r' % (keys, state['loading'], state['error']))

    tabs = pg.evaluate("() => (window.TABS || []).map(t => t.id)")
    print('共 %d 个 Tab\n' % len(tabs))
    res = []
    for t in tabs:
        n0 = len(errs)
        pg.evaluate("(t) => { window.__e=''; try { switchTab(t); } catch(e) { window.__e=String(e); } }", t)
        pg.wait_for_timeout(650)
        info = pg.evaluate("""() => { const m = document.getElementById('main');
            return {tab: state.tab, len: m.innerText.replace(/\\s+/g,' ').trim().length,
                    cards: m.querySelectorAll('.card').length, err: window.__e}; }""")
        res.append((t, info, len(errs) - n0))

    print('逐 Tab：')
    for t, info, de in res:
        good = info['err'] == '' and de == 0 and info['tab'] == t and info['len'] > 0
        if not good:
            ok = False
        print('  %s %-15s tab=%-15s 文本 %5d | 卡片 %2d | 新错误 %d %s'
              % ('✅' if good else '❌', t, info['tab'], info['len'], info['cards'], de,
                 ('| ' + info['err'][:50]) if info['err'] else ''))

    # 待办 Tab 专项复检（改动集中区）
    pg.evaluate("() => switchTab('todos')")
    pg.wait_for_timeout(1500)
    td = pg.evaluate("""() => {
      const T = e => (e ? e.innerText.replace(/\\s+/g,' ').trim() : '');
      return {hasForm: !!document.getElementById('todoCat'),
              opts: (() => { const s=document.getElementById('todoCat'); return s?s.querySelectorAll('option').length:0; })(),
              heads: [...new Set([...document.querySelectorAll('#main div[style*="font-weight:800"]')].map(T))],
              rows: document.querySelectorAll('.todo-item').length};
    }""")
    chk('待办 Tab 复检', td['hasForm'] and td['opts'] == 9 and len(td['heads']) == 2 and td['rows'] > 0,
        json.dumps(td, ensure_ascii=False))
    chk('全程无 JS 错误', not errs, str(errs[:2]))

    pg.evaluate("([k]) => { localStorage.removeItem(k); localStorage.removeItem('bior_auth_token'); localStorage.removeItem('bior_sw_user_v2'); }", [KEY])
    br.close()

print('\n%s' % ('✅ P0 回归通过：其余 Tab 未受影响' if ok else '❌ 回归发现问题'))
sys.exit(0 if ok else 1)
