from __future__ import annotations

import os
import sys
from pathlib import Path

from dotenv import load_dotenv
from playwright.sync_api import sync_playwright

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

from e2e.pages.tenant_auth_page import TenantAuthPage


load_dotenv()
sys.stdout.reconfigure(encoding="utf-8")

WZG_CONSOLE_URL = "https://test-merchant-lianlianyun.lianlianwz.com/productConsole?productCode=P20251204180120231330"
OUT_DIR = Path("runtime/push_probe")


def safe_name(name: str) -> str:
    return name.replace("/", "_").replace("\\", "_").replace(":", "_")


def dump(page, name: str) -> None:
    OUT_DIR.mkdir(parents=True, exist_ok=True)
    name = safe_name(name)
    page.wait_for_timeout(1500)
    text = page.locator("body").inner_text(timeout=5000)
    state = page.evaluate(
        """() => ({
            url: location.href,
            text: document.body.innerText,
            inputs: Array.from(document.querySelectorAll('input, textarea')).map(el => ({
                placeholder: el.getAttribute('placeholder') || '',
                value: el.value || '',
                type: el.getAttribute('type') || '',
                rect: (() => { const r = el.getBoundingClientRect(); return {x:r.x,y:r.y,width:r.width,height:r.height}; })()
            })),
            buttons: Array.from(document.querySelectorAll('button')).map(el => ({
                text: (el.innerText || el.textContent || '').trim(),
                rect: (() => { const r = el.getBoundingClientRect(); return {x:r.x,y:r.y,width:r.width,height:r.height}; })()
            })),
            selects: Array.from(document.querySelectorAll('.ant-select-selector')).map(el => ({
                text: (el.innerText || el.textContent || '').trim(),
                rect: (() => { const r = el.getBoundingClientRect(); return {x:r.x,y:r.y,width:r.width,height:r.height}; })()
            }))
        })"""
    )
    (OUT_DIR / f"{name}.txt").write_text(str(state), encoding="utf-8")
    page.screenshot(path=str(OUT_DIR / f"{name}.png"), full_page=True)
    print(f"[{name}] {page.url}\n{text[:3000]}")
    print("[inputs]", state["inputs"])
    print("[buttons]", state["buttons"])
    print("[selects]", state["selects"])
    for index, frame in enumerate(page.frames):
        if frame == page.main_frame:
            continue
        try:
            frame_text = frame.locator("body").inner_text(timeout=2000)
            (OUT_DIR / f"{name}_frame_{index}.txt").write_text(
                f"URL: {frame.url}\n\n{frame_text}",
                encoding="utf-8",
            )
            print(f"[frame {index}] {frame.url}\n{frame_text[:2000]}")
        except Exception as exc:
            print(f"[frame {index}] {frame.url} dump failed: {exc}")


def click_sidebar_text(page, text: str, nth: int = 0, right_edge: bool = False) -> bool:
    boxes = page.evaluate(
        """text => Array.from(document.querySelectorAll('taro-view-core, div, span'))
            .map(el => ({ text: (el.innerText || el.textContent || '').trim(), r: el.getBoundingClientRect() }))
            .filter(item => item.r.x >= 0 && item.r.x < 240 && item.r.y > 40)
            .filter(item => item.r.width > 20 && item.r.width < 240 && item.r.height > 10)
            .filter(item => item.text === text || item.text.split(/\\s+/).includes(text))
            .sort((a, b) => {
                if (a.text === text && b.text !== text) return -1;
                if (b.text === text && a.text !== text) return 1;
                return a.r.y - b.r.y || (a.r.width * a.r.height) - (b.r.width * b.r.height);
            })
            .map(item => ({ x: item.r.x, y: item.r.y, width: item.r.width, height: item.r.height, text: item.text }))""",
        text,
    )
    print(f"[click candidates {text}]", boxes)
    if len(boxes) <= nth:
        return False
    box = boxes[nth]
    x = box["x"] + box["width"] - 16 if right_edge else box["x"] + box["width"] / 2
    page.mouse.click(x, box["y"] + box["height"] / 2)
    page.wait_for_load_state("domcontentloaded")
    page.wait_for_timeout(1800)
    return True


def click_button_by_text(page, texts: list[str]) -> bool:
    for text in texts:
        clicked = page.evaluate(
            """text => {
                const nodes = Array.from(document.querySelectorAll('button, taro-button-core, taro-view-core, div, span'));
                const target = nodes.find(el => {
                    const value = (el.innerText || el.textContent || '').trim();
                    const r = el.getBoundingClientRect();
                    return r.width > 0 && r.height > 0 && (value === text || value.includes(text));
                });
                if (!target) return false;
                target.click();
                return true;
            }""",
            text,
        )
        if clicked:
            page.wait_for_timeout(1500)
            return True
    return False


def click_button_in_frames(page, texts: list[str]) -> bool:
    if click_button_by_text(page, texts):
        return True
    for frame in page.frames:
        for text in texts:
            try:
                clicked = frame.evaluate(
                    """text => {
                        const nodes = Array.from(document.querySelectorAll('button, taro-button-core, taro-view-core, div, span'));
                        const target = nodes.find(el => {
                            const value = (el.innerText || el.textContent || '').trim();
                            const r = el.getBoundingClientRect();
                            return r.width > 0 && r.height > 0 && (value === text || value.includes(text));
                        });
                        if (!target) return false;
                        target.click();
                        return true;
                    }""",
                    text,
                )
                if clicked:
                    page.wait_for_timeout(1800)
                    return True
            except Exception:
                continue
    return False


def main() -> None:
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False, slow_mo=120)
        context = browser.new_context(viewport={"width": 1440, "height": 900})
        page = context.new_page()
        auth_page = TenantAuthPage(page, os.getenv("TENANT_HOME_URL", "https://test-lianlianyun.lianlianwz.com/home"))
        auth_page.login_main_account(
            os.getenv("E2E_PROBE_WZG_PHONE", "19147509308"),
            os.getenv("E2E_PROBE_WZG_PASSWORD", "test123456"),
        )
        page.goto(WZG_CONSOLE_URL, wait_until="domcontentloaded")
        page.wait_for_timeout(3000)
        dump(page, "console_start")

        click_sidebar_text(page, "商家管理", right_edge=True)
        dump(page, "after_商家管理")
        # First 工作室管理 under 商家管理.
        click_sidebar_text(page, "工作室管理", nth=0)
        dump(page, "商家管理_工作室管理")
        click_button_in_frames(page, ["添加", "新增", "新 增", "新增授权", "添加授权", "工作室授权", "授权"])
        dump(page, "商家管理_工作室管理_添加")

        page.goto(WZG_CONSOLE_URL, wait_until="domcontentloaded")
        page.wait_for_timeout(2000)
        click_sidebar_text(page, "履约工作室/平台", right_edge=True)
        dump(page, "after_履约工作室平台")
        # First/only 工作室管理 under 履约工作室/平台 if visible.
        click_sidebar_text(page, "工作室管理", nth=0)
        dump(page, "履约工作室平台_工作室管理")
        click_sidebar_text(page, "工作室授权", nth=0)
        dump(page, "履约工作室平台_工作室授权")
        click_button_in_frames(page, ["添加", "新增", "新 增", "新增授权", "添加授权", "工作室授权", "授权"])
        dump(page, "履约工作室平台_工作室授权_添加")

        page.goto(WZG_CONSOLE_URL, wait_until="domcontentloaded")
        page.wait_for_timeout(2000)
        click_sidebar_text(page, "履约工作室/平台", right_edge=True)
        click_sidebar_text(page, "工作室管理", nth=0)
        click_sidebar_text(page, "推单配置", nth=0)
        dump(page, "履约工作室平台_推单配置")
        click_button_in_frames(page, ["新增策略", "新增", "新 增", "添加"])
        dump(page, "履约工作室平台_推单配置_新增")
        browser.close()


if __name__ == "__main__":
    main()
