from __future__ import annotations

import os
import sys
from pathlib import Path

from dotenv import load_dotenv
from playwright.sync_api import 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
from e2e.utils.account_store import account_store


def main() -> None:
    if hasattr(sys.stdout, "reconfigure"):
        sys.stdout.reconfigure(encoding="utf-8")
    load_dotenv(ROOT / ".env")

    source_order_no = os.getenv("E2E_S_FLOW_SOURCE_ORDER_NO", "E2EORDER0623111929").strip()
    sub_order_no = os.getenv("E2E_TARGET_SUB_ORDER_NO", "WY20260630100738271050").strip()
    store = account_store()
    order = next(
        item
        for item in store.load_payload().get("dispatched_orders", [])
        if item.get("source_order_no") == source_order_no
    )
    account = store.find(phone=(order.get("wanyouji_phones") or [""])[0])
    assert account is not None

    with sync_playwright() as playwright:
        browser = playwright.chromium.launch(headless=True)
        context = browser.new_context(viewport={"width": 1920, "height": 1080})
        page = context.new_page()
        try:
            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()
            fulfillment.search_workshop_order_list(frame, source_order_no, order.get("order_title", source_order_no))
            assert fulfillment.open_workshop_order_detail_by_upstream_order_link(
                frame,
                source_order_no,
                order.get("order_title", source_order_no),
            )
            fulfillment.scroll_sub_order_table_to_right(frame)
            info = frame.evaluate(
                """subOrderNo => {
                    const visible = el => {
                      const r = el.getBoundingClientRect();
                      return r.width > 0 && r.height > 0;
                    };
                    const norm = value => String(value || '').replace(/\\s+/g, '');
                    const roots = Array.from(document.querySelectorAll('.ant-modal, .ant-drawer')).filter(visible);
                    const root = roots.pop() || document;
                    const rows = Array.from(root.querySelectorAll('tbody tr.ant-table-row, tbody tr, tr'))
                      .map((row, index) => ({ index, text: row.innerText || row.textContent || '', html: row.outerHTML, r: row.getBoundingClientRect() }))
                      .filter(item => item.r.width > 0 && item.r.height > 0);
                    const target = rows.find(item => item.text.includes(subOrderNo));
                    const rowCenterY = target ? target.r.y + target.r.height / 2 : 0;
                    const sameY = target
                      ? rows.filter(item => Math.abs((item.r.y + item.r.height / 2) - rowCenterY) < Math.max(8, target.r.height / 2))
                      : [];
                    const nodes = Array.from(root.querySelectorAll('button, a, [role="button"], span, div'))
                      .map((el, index) => ({
                        index,
                        tag: el.tagName,
                        cls: String(el.className || ''),
                        role: el.getAttribute('role') || '',
                        text: (el.innerText || el.textContent || '').trim(),
                        normText: norm(el.innerText || el.textContent || ''),
                        r: el.getBoundingClientRect(),
                        html: el.outerHTML.slice(0, 300),
                      }))
                      .filter(item => item.r.width > 0 && item.r.height > 0)
                      .filter(item => target && Math.abs((item.r.y + item.r.height / 2) - rowCenterY) < 30)
                      .sort((a, b) => a.r.x - b.r.x || a.r.width * a.r.height - b.r.width * b.r.height);
                    return {
                      modalText: (root.innerText || root.textContent || '').slice(0, 3000),
                      targetRow: target ? { index: target.index, text: target.text, rect: target.r.toJSON?.() || target.r, html: target.html.slice(0, 1000) } : null,
                      sameYRows: sameY.map(item => ({ index: item.index, text: item.text, rect: item.r.toJSON?.() || item.r, html: item.html.slice(0, 500) })),
                      nearbyNodes: nodes.map(item => ({ ...item, r: item.r.toJSON?.() || item.r })),
                    };
                }""",
                sub_order_no,
            )
            print(info)
            if os.getenv("E2E_CLICK_TARGET_ACTION", "").strip() == "1":
                clicked = frame.evaluate(
                    """subOrderNo => {
                        const visible = el => {
                          const r = el.getBoundingClientRect();
                          return r.width > 0 && r.height > 0;
                        };
                        const roots = Array.from(document.querySelectorAll('.ant-modal, .ant-drawer')).filter(visible);
                        const root = roots.pop() || document;
                        const row = root.querySelector(`tr[data-row-key="${subOrderNo}"]`);
                        const action = Array.from(row?.querySelectorAll('a, button, [role="button"]') || [])
                          .find(el => (el.innerText || el.textContent || '').trim() === '去处理');
                        if (!action) return false;
                        const r = action.getBoundingClientRect();
                        action.dispatchEvent(new MouseEvent('mouseover', { bubbles: true, clientX: r.x + r.width / 2, clientY: r.y + r.height / 2 }));
                        action.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, clientX: r.x + r.width / 2, clientY: r.y + r.height / 2 }));
                        action.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, clientX: r.x + r.width / 2, clientY: r.y + r.height / 2 }));
                        action.click();
                        return true;
                    }""",
                    sub_order_no,
                )
                page.wait_for_timeout(2500)
                after = frame.evaluate(
                    """() => {
                        const visible = el => {
                          const r = el.getBoundingClientRect();
                          return r.width > 0 && r.height > 0;
                        };
                        const roots = Array.from(document.querySelectorAll('.ant-modal, .ant-drawer, .ant-popover, .ant-popconfirm')).filter(visible);
                        return roots.map((root, index) => ({
                          index,
                          cls: String(root.className || ''),
                          text: (root.innerText || root.textContent || '').slice(0, 3000),
                          html: root.outerHTML.slice(0, 3000),
                        }));
                    }"""
                )
                print({"clicked": clicked, "after_click_roots": after})
                if os.getenv("E2E_SUBMIT_TARGET_ACTION", "").strip() == "1":
                    amount = os.getenv("E2E_REVOKE_AUDIT_AMOUNT", "0").strip()
                    remark = os.getenv("E2E_REVOKE_AUDIT_REMARK", "E2E 同意打手撤销").strip()
                    submitted = frame.evaluate(
                        """({ amount, remark }) => {
                            const visible = el => {
                              const r = el.getBoundingClientRect();
                              return r.width > 0 && r.height > 0;
                            };
                            const roots = Array.from(document.querySelectorAll('.ant-modal')).filter(visible);
                            const root = roots[roots.length - 1];
                            if (!root) return { ok: false, reason: 'no modal' };
                            const setValue = (el, value) => {
                              const proto = el.tagName === 'TEXTAREA'
                                ? window.HTMLTextAreaElement.prototype
                                : window.HTMLInputElement.prototype;
                              const setter = Object.getOwnPropertyDescriptor(proto, 'value')?.set;
                              if (setter) setter.call(el, '');
                              else el.value = '';
                              el.dispatchEvent(new InputEvent('input', { bubbles: true, inputType: 'deleteContentBackward', data: '' }));
                              if (setter) setter.call(el, value);
                              else el.value = value;
                              el.dispatchEvent(new InputEvent('input', { bubbles: true, inputType: 'insertText', data: value }));
                              el.dispatchEvent(new Event('change', { bubbles: true }));
                              el.dispatchEvent(new FocusEvent('blur', { bubbles: true }));
                            };
                            const agree = Array.from(root.querySelectorAll('label, .ant-radio-wrapper, span, div'))
                              .find(el => (el.innerText || el.textContent || '').replace(/\\s+/g, '').includes('同意撤销'));
                            agree?.click();
                            const formItems = Array.from(root.querySelectorAll('.ant-form-item, [class*="form-item"]'))
                              .map(el => ({ el, text: el.innerText || el.textContent || '', r: el.getBoundingClientRect() }))
                              .filter(item => item.r.width > 0 && item.r.height > 0);
                            const amountItem = formItems.find(item => item.text.includes('结算金额'));
                            const amountInput = amountItem?.el.querySelector('input:not([disabled]):not([type="file"]):not([type="hidden"])');
                            if (amountInput) setValue(amountInput, amount);
                            const textarea = root.querySelector('textarea:not([disabled])');
                            if (textarea) setValue(textarea, remark);
                            const buttons = Array.from(root.querySelectorAll('.ant-modal-footer button, button'))
                              .map(el => ({ el, text: (el.innerText || el.textContent || '').trim(), r: el.getBoundingClientRect(), disabled: el.disabled, cls: String(el.className || '') }))
                              .filter(item => item.r.width > 0 && item.r.height > 0 && !item.disabled);
                            const confirm = buttons.find(item => item.text.replace(/\\s+/g, '') === '确认') ||
                              buttons.find(item => item.cls.includes('primary')) ||
                              buttons[buttons.length - 1];
                            if (!confirm) return { ok: false, reason: 'no confirm', text: root.innerText || root.textContent || '' };
                            confirm.el.click();
                            return {
                              ok: true,
                              amountFound: Boolean(amountInput),
                              amountValue: amountInput?.value || '',
                              textareaValue: textarea?.value || '',
                              button: confirm.text,
                              text: root.innerText || root.textContent || '',
                            };
                        }""",
                        {"amount": amount, "remark": remark},
                    )
                    page.wait_for_timeout(3500)
                    post_submit = frame.evaluate(
                        """() => {
                            const visible = el => {
                              const r = el.getBoundingClientRect();
                              return r.width > 0 && r.height > 0;
                            };
                            const roots = Array.from(document.querySelectorAll('.ant-modal, .ant-drawer, .ant-popover, .ant-popconfirm, .ant-message, .ant-notification')).filter(visible);
                            return roots.map((root, index) => ({
                              index,
                              cls: String(root.className || ''),
                              text: (root.innerText || root.textContent || '').slice(0, 3000),
                            }));
                        }"""
                    )
                    print({"submitted": submitted, "post_submit_roots": post_submit})
        finally:
            context.close()
            browser.close()


if __name__ == "__main__":
    main()
