"""
8-pov audit: open each admin panel in isolation, verify every element.

Pov: for each of 9 panels:
  - Open panel via the launcher
  - Wait for the panel DOM to be present
  - Take a screenshot
  - Enumerate every <button>, <input>, <select>, <textarea>, <a>
  - Try to click each one (not just read)
  - Record the result (worked / threw / was-disabled / had-no-handler)
  - Verify the panel has visible content (non-empty text)
  - Close the panel
  - Move to the next panel
"""
import asyncio
import json
import sys
from pathlib import Path
from playwright.async_api import async_playwright


PANELS = [
    ("pages", "📄 Pages", "Site pages + regions"),
    ("users", "👥 Users & Roles", "Operators + DAO roles"),
    ("settings", "⚙️ Settings", "Runtime configuration"),
    ("monitor", "📊 Monitor", "Runtime health + drift"),
    ("audit", "🔍 Audit", "Audit log + event bus"),
    ("deploy", "🚀 Deploy", "5-step pipeline + rollback"),
    ("ai", "🤖 AI Agent", "AI proposal + 3-tier approval"),
    ("ai2", "🤖 AI v0.2", "Real LLM prompt + response parse"),
    ("mig", "🔄 Migration", "Analyze + suggest + apply"),
]

URL = "http://localhost:8765/demo/admin-launcher-test.html"
OUT_DIR = Path("/workspace/freshvibe-cms/aux-tests/launcher/audit-pov")
OUT_DIR.mkdir(parents=True, exist_ok=True)


async def main():
    findings = []
    async with async_playwright() as p:
        browser = await p.chromium.launch(
            headless=True,
            executable_path="/root/.cache/ms-playwright/chromium-1223/chrome-linux/chrome",
            args=["--no-sandbox", "--disable-setuid-sandbox", "--disable-gpu"],
            timeout=10000,
        )
        context = await browser.new_context(viewport={"width": 1400, "height": 1400}, bypass_csp=True)
        await context.set_extra_http_headers({"Cache-Control": "no-cache", "Pragma": "no-cache"})
        page = await context.new_page()

        page_errors = []
        page.on("pageerror", lambda e: page_errors.append(str(e)))
        page.on("console", lambda m: page_errors.append(f"console.{m.type}: {m.text}") if m.type == "error" and "favicon" not in m.text else None)

        print(f"opening {URL}...")
        await page.goto(URL, wait_until="networkidle", timeout=10000)
        await page.wait_for_timeout(500)

        # Verify the launcher grid loaded
        buttons = await page.query_selector_all("#buttonGrid .btn")
        print(f"  found {len(buttons)} launcher buttons")
        assert len(buttons) >= 9, f"expected 9+, got {len(buttons)}"

        # Find the panel buttons (not the "open all" green one)
        panel_btns = buttons[:-1]

        for i, (pid, plabel, pdesc) in enumerate(PANELS):
            print(f"\n=== POV {i+1}/9: {plabel} ===")
            await page.evaluate("""() => {
                document.querySelectorAll('[data-panel-id]').forEach(p => p.remove());
            }""")
            await page.wait_for_timeout(100)

            panel_finding = {
                "id": pid,
                "label": plabel,
                "clicked_launcher": False,
                "panel_found": False,
                "panel_visible": False,
                "panel_text_len": 0,
                "panel_text_sample": "",
                "elements": [],
                "errors": [],
                "screenshot": str(OUT_DIR / f"{pid}-panel.png"),
            }

            # Click the launcher button
            try:
                await panel_btns[i].click()
                panel_finding["clicked_launcher"] = True
            except Exception as e:
                panel_finding["errors"].append(f"launcher click failed: {e}")
                findings.append(panel_finding)
                continue

            # Wait for the panel to appear in the DOM
            try:
                await page.wait_for_selector(f'[data-panel-id^="fvcms-"]', timeout=3000)
                panel_finding["panel_found"] = True
            except Exception as e:
                panel_finding["errors"].append(f"panel not found in DOM: {e}")
                await page.screenshot(path=panel_finding["screenshot"])
                findings.append(panel_finding)
                continue

            # The launcher now passes tile positions via tilePosition(idx).
            # Don't override; just bump z-index so the panel sits above
            # the test page's launcher grid.
            await page.evaluate("""() => {
                const panels = document.querySelectorAll('[data-panel-id]');
                panels.forEach((p) => {
                    p.style.zIndex = '99999';
                });
            }""")
            await page.wait_for_timeout(300)

            # Is the panel visible? (has a non-zero bounding box)
            box = await page.evaluate("""() => {
                const p = document.querySelector('[data-panel-id]');
                if (!p) return null;
                const r = p.getBoundingClientRect();
                return { width: r.width, height: r.height, x: r.left, y: r.top };
            }""")
            if box and box["width"] > 50 and box["height"] > 50:
                panel_finding["panel_visible"] = True

            # Get the panel's text content
            text = await page.evaluate("""() => {
                const p = document.querySelector('[data-panel-id]');
                if (!p) return '';
                return p.innerText || p.textContent || '';
            }""")
            panel_finding["panel_text_len"] = len(text)
            panel_finding["panel_text_sample"] = text[:300].replace("\n", " | ")

            # Enumerate every interactive element inside the panel,
            # in document order. The previous version used per-tag index
            # which broke when the panel had multiple buttons + inputs
            # (e.g. settings has 3 selects + 1 text + 1 checkbox + 1 button
            # — the test's per-tag querySelectorAll index didn't match
            # the original enumeration).
            elements = await page.evaluate("""() => {
                const p = document.querySelector('[data-panel-id]');
                if (!p) return [];
                const els = p.querySelectorAll('button, input, select, textarea, a, [role="button"]');
                return Array.from(els).map((e, i) => ({
                    idx: i,
                    tag: e.tagName.toLowerCase(),
                    type: e.type || null,
                    text: (e.innerText || e.value || e.placeholder || '').substring(0, 80).trim(),
                    disabled: e.disabled || false,
                    hasClick: typeof e.onclick === 'function' || e.getAttribute('onclick') !== null || !!e.__eventListeners,
                    id: e.id || null,
                    className: (e.className || '').toString().substring(0, 80),
                    // Add data-audit-id so we can find the same element
                    // again without re-querying by tag
                    auditId: `audit-el-${i}`,
                }));
            }""")

            # Inject audit-id attributes so we can find the same element again
            if elements:
                await page.evaluate("""(n) => {
                    const p = document.querySelector('[data-panel-id]');
                    if (!p) return;
                    const els = p.querySelectorAll('button, input, select, textarea, a, [role="button"]');
                    els.forEach((e, i) => e.setAttribute('data-audit-id', `audit-el-${i}`));
                }""", len(elements))

            # Try to click each element. Use data-audit-id (set above)
            # for reliable re-finding. Skip ALL panel-manager chrome
            # buttons by class.
            click_results = []
            for el in elements:
                tag = el["tag"]
                text = el["text"]
                className = el.get("className", "")
                audit_id = el.get("auditId")
                if tag == "button" and any(c in className for c in ["fvcms-pm-btn", "fvcms-pm-close", "fvcms-pm-collapse", "fvcms-pm-squeeze", "fvcms-pm-detach"]):
                    click_results.append({**el, "result": "skipped-panel-chrome"})
                    continue
                if el["disabled"]:
                    click_results.append({**el, "result": "disabled"})
                    continue
                if not text and tag in ("input", "textarea"):
                    try:
                        sel = f'[data-panel-id] [data-audit-id="{audit_id}"]'
                        handle = await page.query_selector(sel)
                        if handle:
                            await handle.fill("audit-test-input")
                            click_results.append({**el, "result": "filled"})
                        else:
                            click_results.append({**el, "result": "element-missing"})
                    except Exception as e:
                        click_results.append({**el, "result": f"fill-failed: {str(e)[:50]}"})
                    continue
                try:
                    sel = f'[data-panel-id] [data-audit-id="{audit_id}"]'
                    handle = await page.query_selector(sel)
                    if handle:
                        # Scroll the element into view (panels in tile rows
                        # 2 and 3 are at y=860 and y=1260, beyond the
                        # 900px viewport)
                        await handle.scroll_into_view_if_needed(timeout=2000)
                        await handle.click(timeout=3000)
                        # If we just clicked Run pipeline, wait for it to
                        # finish (5 steps × 800ms = 4 seconds)
                        if "Run pipeline" in text or "Run" in text and "pipeline" in text.lower():
                            await page.wait_for_timeout(5000)
                        click_results.append({**el, "result": "clicked-ok"})
                    else:
                        click_results.append({**el, "result": "element-missing"})
                except Exception as e:
                    err = str(e).split("\n")[0][:80]
                    click_results.append({**el, "result": f"click-failed: {err}"})

            panel_finding["elements"] = click_results
            panel_finding["elements_count"] = len(elements)
            panel_finding["elements_clicked_ok"] = sum(1 for c in click_results if c["result"] == "clicked-ok")
            panel_finding["elements_failed"] = sum(1 for c in click_results if c["result"].startswith("click-failed") or c["result"].startswith("fill-failed"))
            panel_finding["elements_skipped"] = sum(1 for c in click_results if c["result"].startswith("skipped"))

            # Screenshot the panel
            await page.screenshot(path=panel_finding["screenshot"], full_page=True)

            # Verify
            print(f"  panel_visible: {panel_finding['panel_visible']}")
            print(f"  panel_text_len: {panel_finding['panel_text_len']}")
            print(f"  elements found: {panel_finding['elements_count']}, clicked: {panel_finding['elements_clicked_ok']}, failed: {panel_finding['elements_failed']}, skipped: {panel_finding['elements_skipped']}")
            if panel_finding["panel_text_len"] < 20:
                panel_finding["errors"].append(f"panel text too short ({panel_finding['panel_text_len']} chars)")
            if panel_finding["elements_count"] == 0:
                panel_finding["errors"].append("no interactive elements in panel")

            findings.append(panel_finding)

        # Final dump
        await page.screenshot(path=str(OUT_DIR / "final-state.png"), full_page=True)
        await browser.close()

    # Write findings
    out_file = OUT_DIR / "findings.json"
    out_file.write_text(json.dumps({"findings": findings, "page_errors": page_errors}, indent=2))
    print(f"\n— Audit complete. {len(findings)} panels inspected. Findings: {out_file}")

    # Summary
    print("\n" + "="*70)
    print("SUMMARY")
    print("="*70)
    for f in findings:
        status = "✓" if not f["errors"] else "✗"
        print(f"  {status} {f['label']}: visible={f['panel_visible']}, text={f['panel_text_len']}c, elems={f['elements_count']} (ok={f.get('elements_clicked_ok', 0)}, fail={f.get('elements_failed', 0)})")
        for e in f["errors"]:
            print(f"      ERROR: {e}")
    if page_errors:
        print(f"\n  Page errors: {len(page_errors)}")
        for e in page_errors[:5]:
            print(f"    {e}")


if __name__ == "__main__":
    asyncio.run(main())
