"""
[已废弃 — 本 spec 不使用]

H5 原型页面批量截图脚本（全页面截图，430×932 视口）。
已被 anchor_compare.py 的逐段截图方案（430×752 视口）取代。

保留原因：仍可用于快速获取全页面参考截图，但不作为像素对比的输入源。
替代工具：scripts/ops/anchor_compare.py extract-h5 <page>

原始参数：iPhone 15 Pro Max: 430×932, DPR:3 → 输出 1290×N 像素 PNG
"""
import asyncio
import sys
from pathlib import Path

from playwright.async_api import async_playwright, Page

BASE_URL = "http://127.0.0.1:5500/docs/h5_ui/pages"
OUT_DIR = Path(__file__).resolve().parents[2] / "docs" / "h5_ui" / "screenshots"

# 确保输出目录存在
OUT_DIR.mkdir(parents=True, exist_ok=True)

# 21 个默认态页面
DEFAULT_PAGES = [
    "login", "apply", "reviewing", "no-permission",
    "task-list", "task-detail", "task-detail-priority",
    "task-detail-relationship", "task-detail-callback",
    "performance", "performance-records",
    "board-finance", "board-customer", "board-coach",
    "coach-detail", "customer-detail", "customer-service-records",
    "chat", "chat-history", "notes", "my-profile",
]

HIDE_SCROLLBAR_JS = """
() => {
    document.documentElement.style.overflow = 'auto';
    document.documentElement.style.scrollbarWidth = 'none';
    const s = document.createElement('style');
    s.textContent = '::-webkit-scrollbar { display: none !important; }';
    document.head.appendChild(s);
}
"""


async def setup_page(page: Page, url: str) -> None:
    """导航到页面，等待 Tailwind CDN 渲染，隐藏滚动条"""
    # Go Live 的 WebSocket 长连接会阻止 networkidle，改用 load
    await page.goto(url, wait_until="load", timeout=15000)
    await page.wait_for_timeout(2500)  # Tailwind CDN JIT 渲染
    await page.evaluate(HIDE_SCROLLBAR_JS)
    await page.wait_for_timeout(300)


async def take_screenshot(page: Page, name: str) -> dict:
    """截取全页截图并返回文件信息"""
    out_path = OUT_DIR / f"{name}.png"
    await page.screenshot(path=str(out_path), full_page=True)
    size = out_path.stat().st_size
    return {"name": name, "size": size, "path": str(out_path)}


async def get_page_functions(page: Page) -> list[str]:
    """获取页面内联 script 中定义的函数名"""
    return await page.evaluate("""
        () => {
            const scripts = document.querySelectorAll('script:not([src])');
            const fns = [];
            for (const s of scripts) {
                const matches = s.textContent.matchAll(/function\\s+(\\w+)/g);
                for (const m of matches) fns.push(m[1]);
            }
            return fns;
        }
    """)


async def screenshot_default_pages(page: Page) -> list[dict]:
    """截取所有默认态页面"""
    results = []
    for name in DEFAULT_PAGES:
        url = f"{BASE_URL}/{name}.html"
        await setup_page(page, url)
        info = await take_screenshot(page, name)
        print(f"  ✅ {name} ({info['size']:,} bytes)")
        results.append(info)
    return results



async def screenshot_interactive_pages(page: Page) -> list[dict]:
    """截取所有交互态页面 — 全部用 DOM class 操作，不依赖闭包内函数"""
    results = []

    # --- task-list: context menu ---
    await setup_page(page, f"{BASE_URL}/task-list.html")
    # showContextMenu 在 IIFE 闭包内，改用 DOM class 操作
    await page.evaluate("""
        () => {
            const overlay = document.getElementById('contextOverlay');
            const menu = document.getElementById('contextMenu');
            if (overlay) overlay.classList.add('active');
            if (menu) {
                menu.style.left = '120px';
                menu.style.top = '300px';
                menu.classList.add('active');
            }
        }
    """)
    await page.wait_for_timeout(500)
    info = await take_screenshot(page, "task-list--context-menu")
    print(f"  ✅ task-list--context-menu ({info['size']:,} bytes)")
    results.append(info)

    # --- task-list: note modal ---
    await setup_page(page, f"{BASE_URL}/task-list.html")
    # remarkModal 通过 .active class 显示
    await page.evaluate("""
        () => {
            const modal = document.getElementById('remarkModal');
            if (modal) modal.classList.add('active');
        }
    """)
    await page.wait_for_timeout(500)
    info = await take_screenshot(page, "task-list--note-modal")
    print(f"  ✅ task-list--note-modal ({info['size']:,} bytes)")
    results.append(info)

    # --- task-detail: note modal ---
    await setup_page(page, f"{BASE_URL}/task-detail.html")
    await page.evaluate("""
        () => {
            const modal = document.getElementById('noteModal');
            if (modal) {
                modal.classList.add('active');
                modal.classList.remove('hidden');
                modal.style.display = '';
            }
        }
    """)
    await page.wait_for_timeout(500)
    info = await take_screenshot(page, "task-detail--note-modal")
    print(f"  ✅ task-detail--note-modal ({info['size']:,} bytes)")
    results.append(info)

    # --- task-detail: abandon modal ---
    await setup_page(page, f"{BASE_URL}/task-detail.html")
    await page.evaluate("""
        () => {
            const modal = document.getElementById('abandonModal');
            if (modal) {
                modal.classList.add('active');
                modal.classList.remove('hidden');
                modal.style.display = '';
            }
        }
    """)
    await page.wait_for_timeout(500)
    info = await take_screenshot(page, "task-detail--abandon-modal")
    print(f"  ✅ task-detail--abandon-modal ({info['size']:,} bytes)")
    results.append(info)

    # --- coach-detail: note modal ---
    await setup_page(page, f"{BASE_URL}/coach-detail.html")
    await page.evaluate("""
        () => {
            const popup = document.getElementById('notesPopup');
            if (popup) {
                popup.classList.add('active', 'show');
                popup.classList.remove('hidden');
                popup.style.display = '';
            }
        }
    """)
    await page.wait_for_timeout(500)
    info = await take_screenshot(page, "coach-detail--note-modal")
    print(f"  ✅ coach-detail--note-modal ({info['size']:,} bytes)")
    results.append(info)

    return results



async def screenshot_board_finance_interactive(page: Page) -> list[dict]:
    """board-finance 交互态截图 — 用 DOM class 操作"""
    results = []

    # filter dropdown (时间筛选)
    await setup_page(page, f"{BASE_URL}/board-finance.html")
    await page.evaluate("""
        () => {
            const overlay = document.getElementById('filterOverlay');
            const dropdown = document.getElementById('timeDropdown');
            const bar = document.getElementById('filterBar');
            if (overlay) overlay.classList.add('show');
            if (dropdown) {
                // 定位到筛选栏下方
                if (bar) {
                    const rect = bar.getBoundingClientRect();
                    dropdown.style.top = rect.bottom + 'px';
                }
                dropdown.classList.add('show');
            }
        }
    """)
    await page.wait_for_timeout(500)
    info = await take_screenshot(page, "board-finance--filter-dropdown")
    print(f"  ✅ board-finance--filter-dropdown ({info['size']:,} bytes)")
    results.append(info)

    # tip modal
    await setup_page(page, f"{BASE_URL}/board-finance.html")
    await page.evaluate("""
        () => {
            const toast = document.getElementById('tipToast');
            const overlay = document.getElementById('tipOverlay');
            const titleEl = document.getElementById('tipTitle');
            const contentEl = document.getElementById('tipContent');
            if (titleEl) titleEl.textContent = '发生额/正价';
            if (contentEl) contentEl.innerHTML = '<strong>发生额</strong>：所有订单的原价总和（不扣优惠）\\n用于衡量门店整体业务规模';
            if (overlay) overlay.classList.add('show');
            if (toast) toast.classList.add('show');
        }
    """)
    await page.wait_for_timeout(500)
    info = await take_screenshot(page, "board-finance--tip-modal")
    print(f"  ✅ board-finance--tip-modal ({info['size']:,} bytes)")
    results.append(info)

    # toc panel
    await setup_page(page, f"{BASE_URL}/board-finance.html")
    await page.evaluate("""
        () => {
            const dropdown = document.getElementById('tocDropdown');
            const overlay = document.getElementById('tocOverlay');
            if (dropdown) dropdown.classList.add('show');
            if (overlay) overlay.classList.add('show');
        }
    """)
    await page.wait_for_timeout(500)
    info = await take_screenshot(page, "board-finance--toc-panel")
    print(f"  ✅ board-finance--toc-panel ({info['size']:,} bytes)")
    results.append(info)

    return results


async def screenshot_board_coach_interactive(page: Page) -> list[dict]:
    """board-coach 交互态截图 — 用 DOM class 操作切换维度容器"""
    results = []

    # 4 个排序维度切换：直接操作 dim-container 的 active class
    sort_dims = [
        ("perf-high", "dim-perf", "定档业绩最高"),
        ("salary-high", "dim-salary", "工资最高"),
        ("storage-value", "dim-sv", "客源储值最高"),
        ("task-complete", "dim-task", "任务完成最多"),
    ]
    for suffix, dim_id, label_text in sort_dims:
        await setup_page(page, f"{BASE_URL}/board-coach.html")
        await page.evaluate(f"""
            () => {{
                // 切换维度容器
                document.querySelectorAll('.dim-container').forEach(el => el.classList.remove('active'));
                const target = document.getElementById('{dim_id}');
                if (target) target.classList.add('active');
                // 更新排序标签
                const label = document.getElementById('sortLabel');
                if (label) label.textContent = '{label_text}';
            }}
        """)
        await page.wait_for_timeout(500)
        info = await take_screenshot(page, f"board-coach--{suffix}")
        print(f"  ✅ board-coach--{suffix} ({info['size']:,} bytes)")
        results.append(info)

    # 3 个筛选下拉：直接操作 dropdown 的 show class
    filter_types = [
        ("sort-dropdown", "sortDropdown"),
        ("skill-dropdown", "skillDropdown"),
        ("time-dropdown", "timeDropdown"),
    ]
    for suffix, dropdown_id in filter_types:
        await setup_page(page, f"{BASE_URL}/board-coach.html")
        await page.evaluate(f"""
            () => {{
                const overlay = document.getElementById('filterOverlay');
                const dropdown = document.getElementById('{dropdown_id}');
                const bar = document.getElementById('filterBar');
                if (overlay) overlay.classList.add('show');
                if (dropdown) {{
                    // 定位到筛选栏下方
                    if (bar) {{
                        const rect = bar.getBoundingClientRect();
                        dropdown.style.top = rect.bottom + 'px';
                    }}
                    dropdown.classList.add('show');
                }}
            }}
        """)
        await page.wait_for_timeout(500)
        info = await take_screenshot(page, f"board-coach--{suffix}")
        print(f"  ✅ board-coach--{suffix} ({info['size']:,} bytes)")
        results.append(info)

    return results



async def screenshot_board_customer_interactive(page: Page) -> list[dict]:
    """board-customer 交互态截图 — 用 DOM class 操作切换维度容器"""
    results = []

    # 8 个维度切换：直接操作 dim-container 的 active class
    customer_dims = [
        ("recall", "dim-recall", "最应召回"),
        ("potential", "dim-potential", "最大消费潜力"),
        ("balance", "dim-balance", "最高余额"),
        ("recharge", "dim-recharge", "最近充值"),
        ("recent", "dim-recent", "最近到店"),
        ("spend60", "dim-spend60", "最高消费 近60天"),
        ("freq60", "dim-freq60", "最频繁 近60天"),
        ("loyal", "dim-loyal", "最专一 近60天"),
    ]
    for suffix, dim_id, label_text in customer_dims:
        await setup_page(page, f"{BASE_URL}/board-customer.html")
        await page.evaluate(f"""
            () => {{
                // 切换维度容器
                document.querySelectorAll('.dim-container').forEach(el => el.classList.remove('active'));
                const target = document.getElementById('{dim_id}');
                if (target) target.classList.add('active');
                // 更新类型标签
                const label = document.getElementById('typeLabel');
                if (label) label.textContent = '{label_text}';
            }}
        """)
        await page.wait_for_timeout(500)
        info = await take_screenshot(page, f"board-customer--{suffix}")
        print(f"  ✅ board-customer--{suffix} ({info['size']:,} bytes)")
        results.append(info)

    # 2 个筛选下拉：直接操作 dropdown 的 show class
    filter_types = [
        ("type-dropdown", "typeDropdown"),
        ("project-dropdown", "projectDropdown"),
    ]
    for suffix, dropdown_id in filter_types:
        await setup_page(page, f"{BASE_URL}/board-customer.html")
        await page.evaluate(f"""
            () => {{
                const overlay = document.getElementById('filterOverlay');
                const dropdown = document.getElementById('{dropdown_id}');
                const bar = document.getElementById('filterBar');
                if (overlay) overlay.classList.add('show');
                if (dropdown) {{
                    if (bar) {{
                        const rect = bar.getBoundingClientRect();
                        dropdown.style.top = rect.bottom + 'px';
                    }}
                    dropdown.classList.add('show');
                }}
            }}
        """)
        await page.wait_for_timeout(500)
        info = await take_screenshot(page, f"board-customer--{suffix}")
        print(f"  ✅ board-customer--{suffix} ({info['size']:,} bytes)")
        results.append(info)

    return results


async def main():
    print("=" * 60)
    print("H5 截图 — iPhone 15 Pro Max (430×932, DPR:3)")
    print(f"输出目录: {OUT_DIR}")
    print("=" * 60)

    async with async_playwright() as p:
        # --hide-scrollbars 消除桌面模式下滚动条占宽，保证输出 1290px (430×3)
        browser = await p.chromium.launch(
            headless=False,
            args=["--hide-scrollbars"],
        )
        context = await browser.new_context(
            viewport={"width": 430, "height": 932},
            device_scale_factor=3,
        )
        page = await context.new_page()

        # 验证 DPR
        dpr = await page.evaluate("() => window.devicePixelRatio")
        print(f"\ndevicePixelRatio = {dpr}")
        assert dpr == 3, f"DPR 应为 3，实际为 {dpr}"

        # 1. 默认态截图
        print("\n📸 默认态截图 (21 页):")
        default_results = await screenshot_default_pages(page)

        # 2. 交互态截图
        print("\n📸 交互态截图:")
        interactive_results = await screenshot_interactive_pages(page)

        # 3. board-finance 交互态
        print("\n📸 board-finance 交互态:")
        finance_results = await screenshot_board_finance_interactive(page)

        # 4. board-coach 交互态
        print("\n📸 board-coach 交互态:")
        coach_results = await screenshot_board_coach_interactive(page)

        # 5. board-customer 交互态
        print("\n📸 board-customer 交互态:")
        customer_results = await screenshot_board_customer_interactive(page)

        all_results = (
            default_results + interactive_results +
            finance_results + coach_results + customer_results
        )

        await browser.close()

    # 验证第一张截图的尺寸（读 PNG IHDR chunk，无需 Pillow）
    import struct
    with open(all_results[0]["path"], "rb") as f:
        f.read(16)  # 跳过 PNG 签名(8) + IHDR chunk length(4) + type(4)
        w, h = struct.unpack(">II", f.read(8))
    print(f"\n🔍 验证: {all_results[0]['name']}.png → {w}×{h} px")
    assert w == 1290, f"宽度应为 1290 (430×3)，实际为 {w}"

    print(f"\n✅ 全部完成: {len(all_results)} 张截图")
    print(f"   输出目录: {OUT_DIR}")


if __name__ == "__main__":
    asyncio.run(main())
