"""Shared Playwright browser utilities for Tier 4/5 daemons."""
from __future__ import annotations

import asyncio
import os
import random
import subprocess
import time
from pathlib import Path


def ensure_xvfb(display: str = ":99") -> bool:
    """Start Xvfb virtual display. Returns True if DISPLAY is set after call."""
    if os.environ.get("DISPLAY"):
        return True
    result = subprocess.run(["pgrep", "-f", f"Xvfb {display}"], capture_output=True)
    if result.returncode != 0:
        try:
            subprocess.Popen(
                ["Xvfb", display, "-screen", "0", "1280x720x24", "-ac"],
                stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
            )
            time.sleep(0.5)
        except Exception as e:
            print(f"[xvfb] Failed to start: {e}", flush=True)
            return False
    os.environ["DISPLAY"] = display
    return True


async def launch_browser(profile_dir: Path, headed: bool = True):
    """Launch persistent Chromium context with playwright-stealth applied."""
    from playwright.async_api import async_playwright
    from playwright_stealth import Stealth

    profile_dir.mkdir(parents=True, exist_ok=True)
    for lock in ["SingletonLock", "SingletonCookie", "SingletonSocket"]:
        (profile_dir / lock).unlink(missing_ok=True)

    pw = await async_playwright().start()
    stealth = Stealth()
    browser = await pw.chromium.launch_persistent_context(
        user_data_dir=str(profile_dir),
        headless=not headed,
        channel="chromium",
        ignore_https_errors=True,
        viewport={"width": 1280, "height": 720},
    )
    await stealth.apply_stealth_async(browser)
    page = browser.pages[0] if browser.pages else await browser.new_page()
    return pw, browser, page


async def get_live_page(state: dict, profile_dir: Path, headed: bool = True):
    """Return live page, relaunching browser if dead."""
    page = state.get("page")
    if page:
        try:
            await page.evaluate("1")
            return page
        except Exception:
            pass
    pw, browser, page = await launch_browser(profile_dir, headed)
    state.update(pw=pw, browser=browser, page=page)
    return page


async def simulate_human(page, duration: float = 3.0) -> None:
    """Random mouse/scroll/hover to improve reCAPTCHA v3 behavioral score."""
    start = time.monotonic()
    vp = page.viewport_size or {"width": 1280, "height": 720}
    w, h = vp["width"], vp["height"]
    while time.monotonic() - start < duration:
        action = random.choice(["move", "move", "scroll", "hover"])
        if action == "move":
            await page.mouse.move(
                random.randint(50, w - 50),
                random.randint(50, h - 50),
                steps=random.randint(3, 8),
            )
            await asyncio.sleep(random.uniform(0.2, 0.6))
        elif action == "scroll":
            await page.evaluate(f"window.scrollBy(0, {random.randint(-200, 300)})")
            await asyncio.sleep(random.uniform(0.3, 0.8))
        elif action == "hover":
            await page.evaluate("""() => {
                const els = document.querySelectorAll('a, button, td, th, span');
                if (els.length > 0)
                    els[Math.floor(Math.random() * els.length)]
                        .dispatchEvent(new MouseEvent('mouseover', {bubbles: true}));
            }""")
            await asyncio.sleep(random.uniform(0.3, 0.7))
