from __future__ import annotations

import json
import os
import sys
from pathlib import Path
from typing import Any

from dotenv import load_dotenv
from playwright.sync_api import Frame, Page, sync_playwright

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

from e2e.pages.wanzhanggui_order_page import WanyoujiFulfillmentPage, WanzhangguiOrderPage
from e2e.utils.account_store import account_store


OUTPUT_PATH = Path("runtime/probes/order_branch_rules.json")


def visible_row_snapshot(frame: Frame, keyword: str) -> dict[str, Any]:
    return frame.evaluate(
        """keyword => {
            const visible = el => {
                const r = el.getBoundingClientRect();
                const style = window.getComputedStyle(el);
                return r.width > 0 && r.height > 0 && style.visibility !== 'hidden' && style.display !== 'none';
            };
            const rows = Array.from(document.querySelectorAll('tbody tr, .ant-table-row, .semi-table-row, tr'))
              .map(row => ({ row, text: (row.innerText || row.textContent || '').trim(), r: row.getBoundingClientRect() }))
              .filter(item => visible(item.row))
              .filter(item => item.text.includes(keyword));
            const row = rows[0];
            if (!row) return { found: false, keyword };
            const actions = Array.from(row.row.querySelectorAll('button, a, [role="button"], span'))
              .map(el => ({ text: (el.innerText || el.textContent || '').trim(), r: el.getBoundingClientRect(), disabled: !!el.disabled }))
              .filter(item => item.text && item.r.width > 0 && item.r.height > 0)
              .filter(item => item.text.length <= 20)
              .map(item => item.text);
            return { found: true, keyword, rowText: row.text, actions: Array.from(new Set(actions)) };
        }""",
        keyword,
    )


def all_visible_buttons(frame: Frame) -> list[str]:
    return frame.evaluate(
        """() => {
            const visible = el => {
                const r = el.getBoundingClientRect();
                const style = window.getComputedStyle(el);
                return r.width > 0 && r.height > 0 && style.visibility !== 'hidden' && style.display !== 'none';
            };
            return Array.from(document.querySelectorAll('button, a, [role="button"], span'))
              .map(el => ({ text: (el.innerText || el.textContent || '').trim(), r: el.getBoundingClientRect(), disabled: !!el.disabled }))
              .filter(item => item.text && visible({ getBoundingClientRect: () => item.r, ownerDocument: document }) && !item.disabled)
              .filter(item => item.text.length <= 24)
              .map(item => item.text)
              .filter((text, index, arr) => arr.indexOf(text) === index);
        }"""
    )


def find_orders() -> list[dict[str, Any]]:
    payload = account_store().load_payload()
    orders = payload.get("dispatched_orders", [])
    interesting = []
    wanted = {"dispatched", "task_accepted", "task_dispatched_to_player_hall", "task_player_accepted", "delivery_submitted", "upstream_completed", "settlement_verified"}
    for item in reversed(orders):
        if item.get("status") in wanted:
            interesting.append(item)
        if len(interesting) >= 8:
            break
    return interesting


def probe_wanzhanggui(page: Page, phone: str, password: str, orders: list[dict[str, Any]]) -> list[dict[str, Any]]:
    order_page = WanzhangguiOrderPage(page, os.getenv("TENANT_HOME_URL", "https://test-lianlianyun.lianlianwz.com/home"))
    order_page.login_main_account(phone, password)
    frame = order_page.open_order_management()
    snapshots = []
    for order in orders:
        keyword = order["source_order_no"]
        try:
            order_page.search_order_if_possible(frame, keyword)
            page.wait_for_timeout(1000)
            snap = visible_row_snapshot(frame, keyword)
            snap["ledger_status"] = order.get("status")
            snap["order_title"] = order.get("order_title")
            snapshots.append(snap)
        except Exception as exc:
            snapshots.append({"keyword": keyword, "ledger_status": order.get("status"), "error": str(exc)})
    return snapshots


def probe_wanyouji_order_list(page: Page, account: dict[str, str], orders: list[dict[str, Any]]) -> list[dict[str, Any]]:
    fulfillment = WanyoujiFulfillmentPage(page, os.getenv("TENANT_HOME_URL", "https://test-lianlianyun.lianlianwz.com/home"))
    fulfillment.login_main_account(account["phone"], account["password"])
    frame = fulfillment.open_workshop_order_list()
    snapshots = []
    for order in orders:
        if account["phone"] not in order.get("wanyouji_phones", []):
            continue
        keyword = order["source_order_no"]
        try:
            fulfillment.search_workshop_order_list(frame, keyword, order.get("order_title", ""))
            page.wait_for_timeout(1000)
            snap = visible_row_snapshot(frame, keyword)
            snap["ledger_status"] = order.get("status")
            snap["order_title"] = order.get("order_title")
            snapshots.append(snap)
        except Exception as exc:
            snapshots.append({"keyword": keyword, "ledger_status": order.get("status"), "error": str(exc)})
    return snapshots


def probe_wanyouji_settlement(page: Page, account: dict[str, str]) -> dict[str, Any]:
    fulfillment = WanyoujiFulfillmentPage(page, os.getenv("TENANT_HOME_URL", "https://test-lianlianyun.lianlianwz.com/home"))
    fulfillment.login_main_account(account["phone"], account["password"])
    fulfillment.goto("https://test-merchant-lianlianyun.lianlianwz.com/productConsole?productCode=P20250814095939369041")
    fulfillment.wait_for_enterprise_console_shell()
    result: dict[str, Any] = {"account": account["phone"], "pages": []}
    parent = fulfillment.click_sidebar_text_scrolled("结算中心", right_edge=True)
    result["clicked_settlement_center"] = bool(parent)
    page.wait_for_timeout(1200)
    for page_name in ["结算账单-丸友集", "结算明细-丸友集"]:
        page_result: dict[str, Any] = {"page": page_name}
        try:
            clicked = fulfillment.click_sidebar_leaf_precise(page_name) or fulfillment.click_sidebar_text_scrolled(page_name)
            page_result["clicked"] = bool(clicked)
            page.wait_for_timeout(3000)
            frame = fulfillment.owner_settlement_frame(page_name)
            text = frame.locator("body").inner_text(timeout=5000)
            page_result["textSample"] = text[:4000]
            page_result["buttons"] = all_visible_buttons(frame)
            page_result["rows"] = frame.evaluate(
                """() => Array.from(document.querySelectorAll('tbody tr, .ant-table-row, tr'))
                    .map(row => (row.innerText || row.textContent || '').trim())
                    .filter(text => text)
                    .slice(0, 8)"""
            )
        except Exception as exc:
            page_result["error"] = str(exc)
        result["pages"].append(page_result)
    return result


def account_dict(phone: str) -> dict[str, str]:
    account = account_store().find(phone=phone)
    if not account:
        raise AssertionError(f"account not found: {phone}")
    return {"phone": account.phone, "password": account.password}


def main() -> None:
    load_dotenv()
    orders = find_orders()
    wanzhanggui = account_dict(os.getenv("E2E_ORDER_WANZHANGGUI_PHONE", "19147509308"))
    wanyouji_phone = ""
    for order in orders:
        phones = order.get("wanyouji_phones") or []
        if phones:
            wanyouji_phone = phones[0]
            break
    if not wanyouji_phone:
        wanyouji_phone = "19038951373"
    wanyouji = account_dict(wanyouji_phone)

    with sync_playwright() as playwright:
        browser = playwright.chromium.launch(headless=os.getenv("E2E_HEADLESS", "1").lower() not in {"0", "false"})
        context = browser.new_context(viewport={"width": 1920, "height": 1080})
        page = context.new_page()
        result: dict[str, Any] = {
            "orders": [
                {
                    "source_order_no": item.get("source_order_no"),
                    "order_title": item.get("order_title"),
                    "status": item.get("status"),
                    "wanyouji_phones": item.get("wanyouji_phones"),
                }
                for item in orders
            ],
            "wanzhanggui_order_rows": probe_wanzhanggui(page, wanzhanggui["phone"], wanzhanggui["password"], orders),
            "wanyouji_order_rows": probe_wanyouji_order_list(page, wanyouji, orders),
            "wanyouji_settlement": probe_wanyouji_settlement(page, wanyouji),
        }
        OUTPUT_PATH.parent.mkdir(parents=True, exist_ok=True)
        OUTPUT_PATH.write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8")
        print(json.dumps(result, ensure_ascii=True, indent=2))
        context.close()
        browser.close()


if __name__ == "__main__":
    main()
