#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""验收：① 测试报告收集 Tab 已整体下线且无残留连接 ② 其余 Tab 未受影响 ③ 复核页可用。"""
import json
import os
import re
import subprocess
import sys
from playwright.sync_api import sync_playwright

ROOT = '/Users/liuxinyuan/Desktop/Hermes输出-工作类'
BASE = 'http://127.0.0.1:8765/'
USER = '刘新元'
sess = json.load(open(ROOT + '/数据/auth_sessions.json', encoding='utf-8'))
mine = sorted([(v['expire_at'], k, v) for k, v in sess.items() if v.get('name') == USER], reverse=True, key=lambda x: x[0])
TOKEN, IDENT = mine[0][1], dict(mine[0][2])
IDENT['open_id'] = 'ou_preview_only'
IDENT.pop('expire_at', None)

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

# ── 静态：源码级残留 ──
print('① 源码级残留检查')
src = open(ROOT + '/工具/index.html', encoding='utf-8').read()
live = [l for l in src.splitlines() if 'testReport' in l and not l.strip().startswith('//')]
chk('无「活的」testReport 引用', not live, str(live[:2]))
chk('下线处均留注释可回滚',
    src.count("// { id: 'testReport'") == 1 and src.count("// case 'testReport'") == 1)
blk = [b for b in re.findall(r'<script(?![^>]*\bsrc=)[^>]*>([\s\S]*?)</script>', src) if len(b) > 500]
open('/tmp/chk.js', 'w', encoding='utf-8').write(blk[0])
r = subprocess.run(['node', '--check', '/tmp/chk.js'], capture_output=True, text=True)
chk('index.html 内联脚本语法通过', r.returncode == 0, (r.stderr or '').splitlines()[:2])

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("""([tk, idn]) => {
        localStorage.setItem('bior_auth_token', tk);
        localStorage.setItem('bior_sw_user_v2', JSON.stringify(idn));
    }""", [TOKEN, IDENT])
    pg.goto(BASE + '工具/index.html', wait_until='load')
    pg.wait_for_timeout(2500)
    pg.evaluate("""() => { window.state = window.state || {};
        window.state.user = JSON.parse(JSON.stringify(%s));
        if (typeof showApp === 'function') showApp(); }""" % json.dumps(IDENT, ensure_ascii=False))
    pg.evaluate("() => { if (typeof loadData === 'function') loadData(); }")
    for _ in range(20):
        pg.wait_for_timeout(1000)
        st = pg.evaluate("() => ({l: state.loading, n: Object.keys(state.data||{}).length})")
        if st['n'] >= 8 and not st['l']:
            break

    print('\n② Tab 下线（不显示 + 不可达）')
    m = pg.evaluate("""() => ({
        inTabs: (window.TABS||[]).some(t => t.id === 'testReport'),
        visible: (window.__visibleTabs||[]).some(t => t.id === 'testReport'),
        tabCount: (window.TABS||[]).length,
        sidebar: (document.getElementById('sidebar')||{}).innerText || '',
        bottom: (document.getElementById('bottomNav')||{}).innerText || '',
        labels: (window.TABS||[]).map(t => t.label).filter(l => l.indexOf('测试报告') >= 0)
    })""")
    chk('已移出 TABS', not m['inTabs'], 'Tab 数 %d' % m['tabCount'])
    chk('不在可见 Tab 集合', not m['visible'])
    chk('侧栏无该入口', '测试报告收集' not in m['sidebar'])
    chk('移动端底栏无该入口', '测试报告收集' not in m['bottom'])
    chk('标签集合无「测试报告」', not m['labels'], str(m['labels']))

    before = pg.evaluate("() => state.tab")
    pg.evaluate("() => switchTab('testReport')")
    pg.wait_for_timeout(800)
    after = pg.evaluate("() => ({tab: state.tab, len: document.getElementById('main').innerHTML.length})")
    chk('残留调用被忽略（Tab 不变、页面不空白）',
        after['tab'] == before and after['len'] > 200, 'tab %s→%s len=%d' % (before, after['tab'], after['len']))

    print('\n③ 其余 Tab 未受影响')
    tabs = pg.evaluate("() => (window.TABS||[]).map(t => t.id)")
    lens = []
    for t in tabs:
        n0 = len(errs)
        r2 = pg.evaluate("""(t) => { window.__e=''; try { switchTab(t); } catch(e) { window.__e=String(e); }
          const m = document.getElementById('main'); return {tab: state.tab, len: m.innerHTML.length, err: window.__e}; }""", t)
        pg.wait_for_timeout(420)
        lens.append(r2['len'])
        if r2['err'] or r2['tab'] != t or len(errs) - n0:
            ok = False
            print('  ❌ %-14s err=%s newerr=%d' % (t, r2['err'][:40], len(errs) - n0))
    chk('全部 %d 个 Tab 可切换' % len(tabs), True)
    chk('各 Tab 内容不相同', len(set(lens)) >= len(tabs) - 2, '%d 种 / %d 个' % (len(set(lens)), len(lens)))
    chk('全程无 JS 错误', not errs, str(errs[:2]))
    pg.screenshot(path='/tmp/tab_off.png')
    br.close()

print('\n%s' % ('✅ 测试报告收集 Tab 已整体下线，其余未受影响' if ok else '❌ 存在问题'))
sys.exit(0 if ok else 1)
