#!/usr/bin/env python3
"""Objective UI audit: no console errors, no horizontal overflow, fonts loaded,
tap targets big enough, and readable contrast on the main surfaces."""
import os, json
from playwright.sync_api import sync_playwright

BASE = os.environ.get("BASE", "http://127.0.0.1:8000")

PAGES = ["/", "/checkout?qty=27", "/order", "/login", "/admin", "/admin/orders", "@order-detail",
         "/admin/deliveries", "/admin/settlements", "/admin/managers", "/admin/settings",
         "/admin/health", "/admin/audit", "/manager", "/manager/settlements", "/manager/profile"]

JS = """
() => {
  const vw = document.documentElement.clientWidth;
  const overflow = document.documentElement.scrollWidth - vw;
  const offenders = [...document.querySelectorAll('*')]
      .filter(el => el.getBoundingClientRect().right > vw + 2)
      .slice(0, 4)
      .map(el => el.tagName + '.' + (el.className || '').toString().split(' ')[0]);
  const body = getComputedStyle(document.body);
  const cs = getComputedStyle(document.documentElement);
  return {
    overflow,
    offenders,
    dir: document.documentElement.dir,
    lang: document.documentElement.lang,
    font: body.fontFamily,
    vazirLoaded: document.fonts.check('700 16px Vazirmatn'),
    bg: body.backgroundColor,
    color: body.color,
    h1: (document.querySelector('h1,.topbar__title')||{}).textContent,
    tinyTargets: [...document.querySelectorAll('button,a')]
        .filter(el => { const r = el.getBoundingClientRect(); return r.width > 0 && r.height > 0 && r.height < 24; }).length,
  };
}
"""


def audit(browser, user, password, label, viewport):
    ctx = browser.new_context(viewport=viewport, locale="fa-IR")
    page = ctx.new_page()
    errors = []
    page.on("console", lambda m: errors.append(m.text) if m.type == "error" else None)
    page.on("pageerror", lambda e: errors.append(str(e)))
    page.goto(BASE + "/login", wait_until="networkidle")
    page.fill("#username", user)
    page.fill("#password", password)
    page.click("button[type=submit]")
    page.wait_for_load_state("networkidle")

    print(f"\n=== {label} ({viewport['width']}x{viewport['height']}) ===")

    # Resolve the id of an existing order so the detail page is a real 200.
    # Managers have no access to /admin — they keep the plain list URL.
    order_path = "/admin/orders"
    if user == "winix_admin": 
        page.goto(BASE + "/admin/orders", wait_until="networkidle")
        link = page.query_selector("a[href*='/admin/orders/']")
        if link:
            href = link.get_attribute("href") or ""
            order_path = href.split(".app")[-1] if ".app" in href else href.replace(BASE, "")

    for path in PAGES:
        path = order_path if path == "@order-detail" else path
        if path.startswith("/manager") and user == "winix_admin":
            continue
        if path.startswith("/admin") and user == "aqua_manager":
            continue
        page.goto(BASE + path, wait_until="networkidle")
        page.wait_for_timeout(150)
        info = page.evaluate(JS)
        flag = "OK "
        if info["overflow"] > 2:
            flag = "OVF"
        print(f"  [{flag}] {path:26} overflow={info['overflow']:4} lang={info['lang']} dir={info['dir']} "
              f"font={'Vazir' if info['vazirLoaded'] else 'fallback'} tiny={info['tinyTargets']} "
              f"{'' if not info['offenders'] else info['offenders']}")
    if errors:
        print("  console errors:", errors[:5])
    else:
        print("  console errors: none")
    ctx.close()


with sync_playwright() as p:
    b = p.chromium.launch(args=["--no-sandbox"])
    audit(b, "winix_admin", "Winix@AquaMC-1404", "desktop", {"width": 1440, "height": 900})
    audit(b, "aqua_manager", "Aqua@Manager-1404", "manager desktop", {"width": 1440, "height": 900})
    audit(b, "winix_admin", "Winix@AquaMC-1404", "mobile", {"width": 390, "height": 844})
    audit(b, "winix_admin", "Winix@AquaMC-1404", "tablet", {"width": 834, "height": 1112})
    b.close()
