from __future__ import annotations

import json
import os
import sys
from datetime import datetime
from pathlib import Path

from playwright.sync_api import sync_playwright

ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))

from e2e.conftest import settings as settings_fixture
from e2e.pages.wanzhanggui_order_page import WanyoujiFulfillmentPage
from e2e.pages.wanzhanggui_push_page import WANZHANGGUI_CONSOLE_URL


def dump_frame(frame) -> dict:
    return frame.evaluate(
        """() => {
            const visible = el => {
              const r = el.getBoundingClientRect();
              return r.width > 0 && r.height > 0;
            };
            const controlInfo = el => {
              const r = el.getBoundingClientRect();
              let label = el.getAttribute('placeholder') || '';
              for (let node = el.parentElement; node && node !== document.body; node = node.parentElement) {
                const text = (node.innerText || node.textContent || '').replace(/\\s+/g, ' ').trim();
                if (text && text.length < 120) {
                  label = `${label} ${text}`.trim();
                  break;
                }
              }
              return {
                tag: el.tagName,
                placeholder: el.getAttribute('placeholder') || '',
                value: el.value || '',
                label,
                disabled: Boolean(el.disabled),
                readOnly: Boolean(el.readOnly),
                rect: { x: r.x, y: r.y, w: r.width, h: r.height },
              };
            };
            const buttonInfo = el => {
              const r = el.getBoundingClientRect();
              return {
                text: (el.innerText || el.textContent || '').replace(/\\s+/g, ' ').trim(),
                disabled: Boolean(el.disabled),
                rect: { x: r.x, y: r.y, w: r.width, h: r.height },
              };
            };
            return {
              url: location.href,
              text: (document.body.innerText || document.body.textContent || '').replace(/\\s+/g, '\\n').trim(),
              inputs: Array.from(document.querySelectorAll('input, textarea')).filter(visible).map(controlInfo),
              selects: Array.from(document.querySelectorAll('.ant-select-selector, [role="combobox"]')).filter(visible).map(el => {
                const r = el.getBoundingClientRect();
                return {
                  text: (el.innerText || el.textContent || '').replace(/\\s+/g, ' ').trim(),
                  rect: { x: r.x, y: r.y, w: r.width, h: r.height },
                };
              }),
              buttons: Array.from(document.querySelectorAll('button, a, [role="button"]')).filter(visible).map(buttonInfo),
              modals: Array.from(document.querySelectorAll('.ant-modal, .ant-drawer')).filter(visible).map(el => {
                const r = el.getBoundingClientRect();
                return {
                  text: (el.innerText || el.textContent || '').replace(/\\s+/g, '\\n').trim(),
                  rect: { x: r.x, y: r.y, w: r.width, h: r.height },
                };
              }),
            };
        }"""
    )


def best_frame(page):
    frames = [frame for frame in page.frames if frame != page.main_frame]
    candidates = []
    for frame in frames:
        try:
            text = frame.locator("body").inner_text(timeout=1500)
        except Exception:
            continue
        if text.strip():
            candidates.append((len(text), frame))
    if not candidates:
        raise AssertionError(f"no business frame; frames={[frame.url for frame in page.frames]}")
    return sorted(candidates, key=lambda item: item[0], reverse=True)[0][1]


def click_first_action(frame) -> str:
    actions = ["新增", "新 增", "创建", "添加", "编辑", "修改"]
    for action in actions:
        locator = frame.get_by_text(action, exact=True).first
        try:
            if locator.count():
                locator.click(force=True, timeout=1500)
                return action
        except Exception:
            pass
    clicked = frame.evaluate(
        """actions => {
            const nodes = Array.from(document.querySelectorAll('button, a, [role="button"], span'))
              .map(el => ({ el, text: (el.innerText || el.textContent || '').replace(/\\s+/g, '').trim(), r: el.getBoundingClientRect() }))
              .filter(item => item.r.width > 0 && item.r.height > 0)
              .filter(item => actions.some(action => item.text.includes(action.replace(/\\s+/g, ''))));
            const target = nodes[0];
            if (!target) return '';
            (target.el.closest('button, a, [role="button"]') || target.el).click();
            return target.text;
        }""",
        actions,
    )
    return str(clicked or "")


def main() -> None:
    sys.stdout.reconfigure(encoding="utf-8")
    cfg = settings_fixture.__wrapped__()
    phone = os.getenv("E2E_WANZHANGGUI_TENANT_PHONE", cfg.wanzhanggui_tenant_phone)
    password = os.getenv("E2E_WANZHANGGUI_TENANT_PASSWORD", cfg.wanzhanggui_tenant_password)
    out = Path("runtime/probes/wanzhanggui_paycenter_pages") / datetime.now().strftime("%Y%m%d-%H%M%S")
    out.mkdir(parents=True, exist_ok=True)

    result = []
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False, slow_mo=100)
        context = browser.new_context(viewport={"width": cfg.viewport_width, "height": cfg.viewport_height})
        page = context.new_page()
        wzg = WanyoujiFulfillmentPage(page, cfg.tenant_home_url)
        wzg.login_main_account(phone, password)
        page.goto(WANZHANGGUI_CONSOLE_URL, wait_until="domcontentloaded")
        wzg.wait_for_enterprise_console_shell()
        assert wzg.click_sidebar_text_scrolled("支付中心", right_edge=True)
        page.wait_for_timeout(1200)

        for menu in ["交易应用", "交易通道", "账号配置"]:
            clicked = wzg.click_sidebar_leaf_precise(menu) or wzg.click_sidebar_text_scrolled(menu)
            page.wait_for_timeout(3000)
            frame = best_frame(page)
            before = dump_frame(frame)
            action = click_first_action(frame)
            page.wait_for_timeout(1800)
            after = dump_frame(frame)
            result.append({"menu": menu, "clicked": clicked, "action": action, "before": before, "after": after})

        (out / "snapshot.json").write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8")
        page.screenshot(path=str(out / "page.png"), full_page=True)
        context.close()
        browser.close()

    print(out)


if __name__ == "__main__":
    main()
