from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime
from pathlib import Path
import json
import sys
import time

from playwright.sync_api import sync_playwright

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

from e2e.pages.product_solution_admin_page import ProductSolutionAdminPage


@dataclass(frozen=True)
class Settings:
    admin_url: str = "https://test-saas-adminui.lianlianwz.com/pages/home/index"
    admin_username: str = "wangss"
    admin_password: str = "123456"


def main() -> None:
    settings = Settings()
    timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
    out_dir = Path("runtime")
    out_dir.mkdir(exist_ok=True)
    screenshot_path = out_dir / f"prodsol_feature_compare_dom_{timestamp}.png"
    json_path = out_dir / f"prodsol_feature_compare_dom_{timestamp}.json"

    with sync_playwright() as playwright:
        browser = playwright.chromium.launch(headless=False, slow_mo=100)
        page = browser.new_page(viewport={"width": 1920, "height": 1080})
        admin = ProductSolutionAdminPage(page, settings.admin_url)
        admin.login(settings.admin_username, settings.admin_password)

        product_code, product_name = admin.open_any_existing_version_product_view()
        admin.open_feature_compare_config()
        page.wait_for_timeout(1000)
        page.evaluate(
            """() => {
              const compact = (value) => (value || '').replace(/\\s+/g, ' ').trim();
              const describe = (element) => {
                if (!element) return null;
                const rect = element.getBoundingClientRect();
                const path = [];
                let current = element;
                const modal = element.closest('.ant-modal') || document.body;
                for (let index = 0; index < 5 && current && current !== modal; index += 1) {
                  path.push({
                    tag: current.tagName,
                    className: String(current.className || ''),
                    text: compact(current.innerText || current.textContent || '').slice(0, 200),
                  });
                  current = current.parentElement;
                }
                return {
                  tag: element.tagName,
                  type: element.getAttribute('type'),
                  role: element.getAttribute('role'),
                  className: String(element.className || ''),
                  placeholder: element.getAttribute('placeholder'),
                  ariaLabel: element.getAttribute('aria-label'),
                  value: element.value,
                  checked: element.checked,
                  text: compact(element.innerText || element.textContent || '').slice(0, 300),
                  rect: { x: Math.round(rect.x), y: Math.round(rect.y), w: Math.round(rect.width), h: Math.round(rect.height) },
                  path,
                };
              };
              window.__featureCompareEvents = [];
              const pushEvent = (event) => {
                const target = event.target;
                const clickable = target && target.closest ? target.closest('button, a, label, input, textarea, [role="button"], .ant-select, .ant-checkbox-wrapper') : target;
                window.__featureCompareEvents.push({
                  at: new Date().toISOString(),
                  type: event.type,
                  key: event.key || null,
                  target: describe(target),
                  actionTarget: describe(clickable),
                });
              };
              document.addEventListener('click', pushEvent, true);
              document.addEventListener('input', pushEvent, true);
              document.addEventListener('change', pushEvent, true);
              document.addEventListener('keydown', pushEvent, true);
            }"""
        )

        summary = page.evaluate(
            """() => {
              const compact = (value) => (value || '').replace(/\\s+/g, ' ').trim();
              const visible = (element) => !!element && (
                element.offsetParent !== null ||
                element.closest('.ant-checkbox, .ant-input-affix-wrapper, .ant-select')
              );
              const modals = Array.from(document.querySelectorAll('.ant-modal'))
                .filter(element => element.offsetParent !== null);
              const modal = [...modals].reverse().find(element => /功能对比|官网展示预览/.test(element.innerText || ''));
              if (!modal) return { error: 'modal not found' };
              const pathOf = (element) => {
                const parts = [];
                let current = element;
                for (let index = 0; index < 6 && current && current !== modal; index += 1) {
                  parts.push({
                    tag: current.tagName,
                    className: String(current.className || ''),
                    text: compact(current.innerText || current.textContent || '').slice(0, 300),
                    rect: (() => {
                      const rect = current.getBoundingClientRect();
                      return { x: Math.round(rect.x), y: Math.round(rect.y), w: Math.round(rect.width), h: Math.round(rect.height) };
                    })(),
                  });
                  current = current.parentElement;
                }
                return parts;
              };
              const controlSummary = Array.from(modal.querySelectorAll('input, textarea, button, select, [contenteditable], .ant-select, .ant-checkbox'))
                .filter(control => visible(control))
                .map((control, controlIndex) => ({
                  controlIndex,
                  tag: control.tagName,
                  type: control.getAttribute('type'),
                  role: control.getAttribute('role'),
                  className: String(control.className || ''),
                  placeholder: control.getAttribute('placeholder'),
                  ariaLabel: control.getAttribute('aria-label'),
                  value: control.value,
                  checked: control.checked,
                  disabled: control.disabled,
                  text: compact(control.innerText || control.textContent || ''),
                  rect: (() => {
                    const rect = control.getBoundingClientRect();
                    return { x: Math.round(rect.x), y: Math.round(rect.y), w: Math.round(rect.width), h: Math.round(rect.height) };
                  })(),
                  path: pathOf(control),
                }));
              const tables = Array.from(modal.querySelectorAll('.ant-table, table'))
                .filter(table => table.offsetParent !== null);
              return {
                title: compact(modal.querySelector('.ant-modal-title')?.innerText || ''),
                productText: compact(modal.innerText || '').slice(0, 3000),
                controls: controlSummary,
                tableCount: tables.length,
                tables: tables.map((table, tableIndex) => {
                  const rows = Array.from(table.querySelectorAll('.ant-table-tbody > tr, tbody > tr, .ant-table-row'))
                    .filter(row => row.offsetParent !== null);
                  return {
                    tableIndex,
                    className: String(table.className || ''),
                    text: compact(table.innerText || '').slice(0, 1500),
                    headers: Array.from(table.querySelectorAll('th, .ant-table-thead .ant-table-cell'))
                      .filter(cell => cell.offsetParent !== null)
                      .map(cell => compact(cell.innerText || cell.textContent || '')),
                    rows: rows.map((row, rowIndex) => {
                      const cells = Array.from(row.querySelectorAll(':scope > .ant-table-cell, :scope > td, :scope > [role="cell"]'))
                        .filter(cell => cell.offsetParent !== null);
                      return {
                        rowIndex,
                        className: String(row.className || ''),
                        text: compact(row.innerText || row.textContent || '').slice(0, 1000),
                        cellCount: cells.length,
                        cells: cells.map((cell, cellIndex) => ({
                          cellIndex,
                          className: String(cell.className || ''),
                          text: compact(cell.innerText || cell.textContent || ''),
                          html: cell.innerHTML.slice(0, 1200),
                          controls: Array.from(cell.querySelectorAll('input, textarea, button, select, [contenteditable], .ant-select, .ant-checkbox'))
                            .map(control => ({
                              tag: control.tagName,
                              type: control.getAttribute('type'),
                              role: control.getAttribute('role'),
                              className: String(control.className || ''),
                              placeholder: control.getAttribute('placeholder'),
                              ariaLabel: control.getAttribute('aria-label'),
                              value: control.value,
                              checked: control.checked,
                              disabled: control.disabled,
                              visible: visible(control),
                              text: compact(control.innerText || control.textContent || ''),
                            })),
                        })),
                      };
                    }),
                  };
                }),
              };
            }"""
        )

        page.screenshot(path=str(screenshot_path), full_page=True)
        json_path.write_text(json.dumps(summary, ensure_ascii=False, indent=2), encoding="utf-8")
        print(f"product: {product_code}/{product_name}")
        print(f"screenshot: {screenshot_path}")
        print(f"json: {json_path}")
        print(json.dumps(summary, ensure_ascii=False, indent=2)[:3000])

        print("Browser is left open for manual probing. Capturing snapshots every 3 seconds for 5 minutes.")
        for index in range(100):
            try:
                probe_time = datetime.now().strftime("%Y%m%d%H%M%S")
                live_screenshot_path = out_dir / f"prodsol_feature_compare_manual_{timestamp}_{index:03d}_{probe_time}.png"
                live_json_path = out_dir / f"prodsol_feature_compare_manual_{timestamp}_{index:03d}_{probe_time}.json"
                live_summary = page.evaluate(
                    """() => {
                      const compact = (value) => (value || '').replace(/\\s+/g, ' ').trim();
                      const visible = (element) => !!element && (
                        element.offsetParent !== null ||
                        element.closest('.ant-checkbox, .ant-input-affix-wrapper, .ant-select')
                      );
                      const modals = Array.from(document.querySelectorAll('.ant-modal'))
                        .filter(element => element.offsetParent !== null);
                      const modal = [...modals].reverse().find(element => /功能对比|官网展示预览/.test(element.innerText || ''));
                      if (!modal) return { error: 'modal not found' };
                      return {
                        productText: compact(modal.innerText || '').slice(0, 3000),
                        events: window.__featureCompareEvents || [],
                        controls: Array.from(modal.querySelectorAll('input, textarea, button, select, [contenteditable], .ant-select, .ant-checkbox'))
                          .filter(control => visible(control))
                          .map((control, controlIndex) => {
                            const rect = control.getBoundingClientRect();
                            return {
                              controlIndex,
                              tag: control.tagName,
                              type: control.getAttribute('type'),
                              role: control.getAttribute('role'),
                              className: String(control.className || ''),
                              placeholder: control.getAttribute('placeholder'),
                              value: control.value,
                              checked: control.checked,
                              disabled: control.disabled,
                              text: compact(control.innerText || control.textContent || ''),
                              rect: { x: Math.round(rect.x), y: Math.round(rect.y), w: Math.round(rect.width), h: Math.round(rect.height) },
                              parentText: compact(control.parentElement?.innerText || control.parentElement?.textContent || '').slice(0, 500),
                              grandParentClass: String(control.parentElement?.parentElement?.className || ''),
                              grandParentText: compact(control.parentElement?.parentElement?.innerText || control.parentElement?.parentElement?.textContent || '').slice(0, 500),
                            };
                          }),
                      };
                    }"""
                )
                page.screenshot(path=str(live_screenshot_path), full_page=True)
                live_json_path.write_text(json.dumps(live_summary, ensure_ascii=False, indent=2), encoding="utf-8")
                print(f"snapshot {index:03d}: {live_json_path}")
                page.wait_for_timeout(3000)
            except Exception as exc:
                print(f"manual probing stopped: {exc}")
                break
        browser.close()


if __name__ == "__main__":
    main()
