"""
Optional Playwright integration for full-page webpage screenshots.

Playwright is NOT bundled in the app. The user installs it on demand via
'Install Playwright' in the launch dialog or Settings > Advanced. It lives
in a dedicated venv under ~/.mugi/playwright-venv so it does not interfere
with the main application environment.
"""
from __future__ import annotations

import json
import os
import subprocess
import sys

from utils.playwright_runner import (
    playwright_available,
    playwright_launch_kwargs,
    playwright_venv_python,
)

_MUGI_DIR = os.path.expanduser("~/.mugi")
_PLAYWRIGHT_VENV_DIR = os.path.join(_MUGI_DIR, "playwright-venv")
_PLAYWRIGHT_VENV_PYTHON = playwright_venv_python()


def _load_prefs() -> dict:
    try:
        from utils.app_prefs_store import load_app_prefs_cached
        return load_app_prefs_cached()
    except Exception:
        return {}


def _playwright_launch_kwargs(*, stealth: bool = False) -> dict:
    return playwright_launch_kwargs(stealth=stealth)


def capture_webpage_screenshot(url: str, max_width: int = 800, timeout_ms: int = 15000, device_scale_factor: int = 2) -> bytes | None:
    """Take a full-page screenshot of *url* using Playwright (browser from prefs: chromium/chrome/msedge/brave or custom path).

    Returns PNG bytes on success, None on any failure. Never raises.
    ``device_scale_factor`` controls CSS-to-pixel ratio (2 = Retina quality).
    """
    if not playwright_available():
        return None
    launch_kwargs = _playwright_launch_kwargs()
    launch_json = json.dumps(launch_kwargs)
    script = f"""
import sys, json
from playwright.sync_api import sync_playwright
launch_kwargs = json.loads({repr(launch_json)})
pw = sync_playwright().start()
try:
    browser = pw.chromium.launch(**launch_kwargs)
    page = browser.new_page(viewport={{"width": {max_width}, "height": 900}}, device_scale_factor={device_scale_factor})
    page.goto({url!r}, wait_until="networkidle", timeout={timeout_ms})
    data = page.screenshot(full_page=True, type="png")
    sys.stdout.buffer.write(data)
    browser.close()
finally:
    pw.stop()
"""
    try:
        result = subprocess.run(
            [_PLAYWRIGHT_VENV_PYTHON, "-c", script],
            capture_output=True,
            timeout=60,
        )
        if result.returncode == 0 and result.stdout and len(result.stdout) > 500:
            return result.stdout
    except Exception:
        pass
    return None


def playwright_capture_if_enabled(url: str, max_width: int = 600) -> bytes | None:
    """Convenience: return screenshot bytes only if prefs enable Playwright and runtime check passes."""
    prefs = _load_prefs()
    if not prefs.get("use_playwright_screenshots", False):
        return None
    if not playwright_available():
        return None
    return capture_webpage_screenshot(url, max_width=max_width)


def fetch_webpage_html_via_playwright(url: str, timeout_ms: int = 20000) -> str | None:
    """Fetch full HTML of *url* using Playwright (same venv as screenshots).
    Returns HTML string on success, None on failure. Uses stealth-friendly
    launch args to reduce bot detection. Never raises."""
    if not playwright_available():
        return None
    import tempfile
    launch_kwargs = _playwright_launch_kwargs(stealth=True)
    launch_json = json.dumps(launch_kwargs)
    fd, out_path = tempfile.mkstemp(suffix=".html", prefix="mugi_pw_fetch_")
    os.close(fd)
    try:
        script = f"""
import os, json, sys
launch_kwargs = json.loads({repr(launch_json)})
out_path = os.environ.get("MUGI_PW_OUTPUT_PATH", "")
url = {repr(url)}
timeout_ms = {timeout_ms}
from playwright.sync_api import sync_playwright
pw = sync_playwright().start()
try:
    browser = pw.chromium.launch(**launch_kwargs)
    page = browser.new_page(viewport={{"width": 1280, "height": 800}})
    page.goto(url, wait_until="networkidle", timeout=timeout_ms)
    html = page.content()
    browser.close()
    if out_path and html:
        with open(out_path, "w", encoding="utf-8") as f:
            f.write(html)
finally:
    pw.stop()
"""
        env = os.environ.copy()
        env["MUGI_PW_OUTPUT_PATH"] = out_path
        result = subprocess.run(
            [_PLAYWRIGHT_VENV_PYTHON, "-c", script],
            capture_output=True,
            timeout=max(60, (timeout_ms // 1000) + 30),
            env=env,
        )
        if result.returncode == 0 and os.path.isfile(out_path):
            with open(out_path, "r", encoding="utf-8", errors="replace") as f:
                return f.read()
    except Exception:
        pass
    finally:
        try:
            os.unlink(out_path)
        except Exception:
            pass
    return None


def install_playwright(progress_callback=None) -> tuple[bool, str]:
    """Install Playwright into the dedicated venv under ~/.mugi.

    *progress_callback* is an optional callable(str) for status messages.
    Returns (success: bool, message: str).
    """
    def _status(msg: str):
        if progress_callback:
            try:
                progress_callback(msg)
            except Exception:
                pass

    os.makedirs(_MUGI_DIR, exist_ok=True)

    if not os.path.isfile(_PLAYWRIGHT_VENV_PYTHON):
        _status("Creating Playwright virtual environment…")
        py = sys.executable
        try:
            r = subprocess.run(
                [py, "-m", "venv", _PLAYWRIGHT_VENV_DIR],
                capture_output=True,
                text=True,
                timeout=60,
            )
            if r.returncode != 0:
                return False, f"Failed to create venv: {(r.stderr or r.stdout or '').strip()}"
        except Exception as e:
            return False, f"Venv creation error: {e}"

    _status("Installing Playwright package…")
    try:
        r = subprocess.run(
            [_PLAYWRIGHT_VENV_PYTHON, "-m", "pip", "install", "--upgrade", "playwright"],
            capture_output=True,
            text=True,
            timeout=180,
        )
        if r.returncode != 0:
            return False, f"pip install playwright failed: {(r.stderr or r.stdout or '').strip()[:500]}"
    except Exception as e:
        return False, f"pip install error: {e}"

    _status("Downloading Chromium browser…")
    try:
        r = subprocess.run(
            [_PLAYWRIGHT_VENV_PYTHON, "-m", "playwright", "install", "chromium"],
            capture_output=True,
            text=True,
            timeout=300,
        )
        if r.returncode != 0:
            return False, f"playwright install chromium failed: {(r.stderr or r.stdout or '').strip()[:500]}"
    except Exception as e:
        return False, f"Chromium install error: {e}"

    _status("Verifying installation…")
    try:
        from utils.playwright_runner import playwright_available, playwright_browsers_ready

        if playwright_available():
            ready, detail = playwright_browsers_ready(use_cache=False)
            if ready:
                _save_pref("playwright_available", True)
                return True, "Playwright installed successfully."
            return False, detail or "Playwright package installed but browser binaries are missing."
    except Exception as exc:
        return False, f"Verification error: {exc}"
    return False, "Installation finished but Playwright is not importable. Check logs."


def _save_pref(key: str, value) -> None:
    """Write a single key into app_prefs.json."""
    prefs = _load_prefs()
    prefs[key] = value
    try:
        from utils.app_prefs_store import save_app_prefs
        save_app_prefs(prefs)
    except Exception:
        pass
