#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""手机视口验证: 检测页面是否还存在水平溢出/裁切, 并截关键区域图"""
import asyncio, json
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        b = await p.chromium.launch()
        pg = await b.new_page(viewport={"width": 390, "height": 844})
        await pg.goto("file:///root/web_reports/report_20260813.html")
        await pg.wait_for_load_state("networkidle")

        # 1) 全局水平溢出检测: body 是否超出视口
        overflow = await pg.evaluate("""() => {
            const doc = document.documentElement;
            return {docScrollW: doc.scrollWidth, innerW: window.innerWidth,
                    docScrollH: doc.scrollHeight};
        }""")
        print("viewport:", overflow)

        # 2) 找到所有宽度非预期宽的元素(超出视口的块级元素, 排除可滚动容器内部)
        wide = await pg.evaluate("""() => {
            const out = [];
            document.querySelectorAll('body *').forEach(el => {
                const r = el.getBoundingClientRect();
                if (r.width > window.innerWidth + 1) {
                    const cs = getComputedStyle(el);
                    const inScroll = !!el.closest('.scroll-x, .tbl-wrap');
                    if (!inScroll && cs.position !== 'fixed') {
                        out.push({tag: el.tagName, cls: (el.className||'').toString().slice(0,40),
                                  w: Math.round(r.width)});
                    }
                }
            });
            return out.slice(0, 20);
        }""")
        print("wide elems:", json.dumps(wide, ensure_ascii=False))

        # 3) 关键区域是否完整: 检查三个表格的最后一个单元格是否可见且在其容器内
        for sel, name in [("table:has(> tr:first-child th:first-child:is(:nth-child(1)))", "ALL")]:
            pass
        checks = await pg.evaluate("""() => {
            // 七指数全景: 第4行最后一格 “市场宽度”
            const tbl1 = document.querySelectorAll('.tbl-wrap table')[0];
            // 错误归因: 首格因子行
            const f = [...document.querySelectorAll('h3.block')].find(h => h.textContent.includes('错误归因'));
            const t2 = f ? f.nextElementSibling.querySelector('table') : null;
            const d = [...document.querySelectorAll('h3.block')].find(h => h.textContent.includes('盯盘'));
            const t3 = d ? d.nextElementSibling.querySelector('table') : null;
            const info = [];
            if (tbl1) { const last = tbl1.rows[tbl1.rows.length-1].cells[tbl1.rows[0].cells.length-1];
                info.push(['七指数全景末格', last.textContent.trim().slice(0,30), Math.round(last.getBoundingClientRect().right) <= 390]); }
            if (t2) { const last = t2.rows[t2.rows.length-1].cells[2];
                info.push(['错误归因末行说明', last.textContent.trim().slice(0,24), last.getBoundingClientRect().width > 200]); }
            if (t3) { const last = t3.rows[t3.rows.length-1].cells[1];
                info.push(['盯盘末行观察', last.textContent.trim().slice(0,24), last.getBoundingClientRect().width > 250]); }
            return info;
        }""")
        print("checks:", json.dumps(checks, ensure_ascii=False))

        # 4) 截关键区域图(手机视口)
        await pg.screenshot(path="/root/web_reports/mobile_check.png", full_page=False)
        # 滚动到相关区域截图
        for name, kw in [("qizhishu", "七指数全景"), ("cuowu", "错误归因"), ("dingpan", "盯盘")]:
            found = await pg.evaluate("""(kw) => {
                const h = [...document.querySelectorAll('h3.block')].find(x => x.textContent.includes(kw));
                if (!h) return false;
                h.scrollIntoView();
                return true;
            }""", kw)
            if found:
                await pg.wait_for_timeout(300)
                await pg.screenshot(path=f"/root/web_reports/mobile_{name}.png")
        await b.close()

asyncio.run(main())
print("DONE")