"""Browser integration — Playwright-based web automation for skills.

Provides a BrowserTool context manager for JavaScript-heavy sites,
form filling, clicking, and screenshotting.

Uses sync Playwright API (not async) because skills run in subprocesses.

pip dependency: playwright

Usage in skills:

    from alive.integrations.browser import BrowserTool

    with BrowserTool() as browser:
        data = browser.quick_scrape("https://example.com")
        print(data["text"])

    # Or for more control:
    with BrowserTool() as browser:
        page = browser.new_page()
        page.goto("https://example.com")
        page.fill("input#search", "query")
        page.click("button[type=submit]")
        page.wait_for_load_state("networkidle")
        content = page.inner_text(".results")
        page.close()
"""

from __future__ import annotations

import logging
from pathlib import Path
from typing import Any

_log = logging.getLogger("alive")

_DEFAULT_USER_AGENT = (
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
    "AppleWebKit/537.36 (KHTML, like Gecko) "
    "Chrome/120.0.0.0 Safari/537.36"
)


class BrowserTool:
    """Playwright-based browser automation tool.

    Use as a context manager:

        with BrowserTool() as browser:
            data = browser.quick_scrape("https://example.com")

    Args:
        headless: Run browser in headless mode (default: True).
        timeout: Default page timeout in ms (default: 30000).
    """

    def __init__(self, headless: bool = True, timeout: int = 30000) -> None:
        self.headless = headless
        self.timeout = timeout
        self._playwright = None
        self._browser = None

    def __enter__(self):
        try:
            from playwright.sync_api import sync_playwright
        except ImportError:
            raise ImportError(
                "Playwright is required for browser automation.\n"
                "Install: pip install 'alive-agent[browser]'\n"
                "Then run: playwright install chromium"
            )

        self._playwright = sync_playwright().start()
        self._browser = self._playwright.chromium.launch(
            headless=self.headless,
        )
        return self

    def __exit__(self, *args):
        if self._browser:
            try:
                self._browser.close()
            except Exception:
                pass
        if self._playwright:
            try:
                self._playwright.stop()
            except Exception:
                pass
        self._browser = None
        self._playwright = None

    def new_page(self):
        """Create a new browser page with sensible defaults.

        Returns:
            A Playwright Page object.
        """
        if not self._browser:
            raise RuntimeError("BrowserTool must be used as a context manager")

        context = self._browser.new_context(
            viewport={"width": 1280, "height": 720},
            user_agent=_DEFAULT_USER_AGENT,
        )
        page = context.new_page()
        page.set_default_timeout(self.timeout)
        return page

    def quick_scrape(self, url: str) -> dict[str, str]:
        """Quick scrape: navigate to URL, wait for JS, return content.

        Args:
            url: URL to scrape.

        Returns:
            Dict with keys: title, html, text, url.
        """
        page = self.new_page()
        try:
            page.goto(url, wait_until="networkidle")
            content = page.content()
            title = page.title()
            text = page.inner_text("body")
            return {
                "title": title,
                "html": content,
                "text": text[:10000],
                "url": url,
            }
        finally:
            page.close()

    def screenshot(
        self,
        url: str,
        path: str = "/tmp/alive_screenshot.png",
        *,
        full_page: bool = True,
    ) -> str:
        """Take a screenshot of a URL.

        Args:
            url: URL to screenshot.
            path: Where to save the screenshot.
            full_page: Capture full page height (default: True).

        Returns:
            Path to the saved screenshot.
        """
        page = self.new_page()
        try:
            page.goto(url, wait_until="networkidle")
            page.screenshot(path=path, full_page=full_page)
            return path
        finally:
            page.close()

    def fill_and_submit(
        self,
        url: str,
        form_data: dict[str, str],
        submit_selector: str = "button[type=submit]",
    ) -> dict[str, str]:
        """Navigate to URL, fill form fields, and submit.

        Args:
            url: URL with the form.
            form_data: Dict mapping CSS selectors to values.
            submit_selector: CSS selector for the submit button.

        Returns:
            Dict with keys: title, text, url (of the resulting page).
        """
        page = self.new_page()
        try:
            page.goto(url, wait_until="networkidle")
            for selector, value in form_data.items():
                page.fill(selector, value)
            page.click(submit_selector)
            page.wait_for_load_state("networkidle")
            return {
                "title": page.title(),
                "text": page.inner_text("body")[:10000],
                "url": page.url,
            }
        finally:
            page.close()


# ── Setup ──────────────────────────────────────────────────────────────────


def check_browser_installed() -> dict[str, bool]:
    """Check if Playwright and Chromium are installed.

    Returns:
        Dict with keys: playwright_installed, chromium_installed.
    """
    result = {
        "playwright_installed": False,
        "chromium_installed": False,
    }

    try:
        from playwright.sync_api import sync_playwright
        result["playwright_installed"] = True
    except ImportError:
        return result

    # Check if chromium browser is available
    try:
        pw = sync_playwright().start()
        try:
            browser = pw.chromium.launch(headless=True)
            browser.close()
            result["chromium_installed"] = True
        except Exception:
            pass
        finally:
            pw.stop()
    except Exception:
        pass

    return result


def setup_browser(console=None) -> bool:
    """Interactive setup for browser integration.

    Returns True if setup completed successfully.
    """
    import subprocess

    from rich.console import Console
    from rich.panel import Panel

    from alive.integrations import _load_config, _save_config

    con = console or Console()

    con.print(Panel(
        "[bold]Setting up browser automation (Playwright + Chromium)[/]\n\n"
        "This will install:\n"
        "• playwright Python package\n"
        "• Chromium browser (headless)",
        title="[bold cyan]Browser Setup[/]",
        border_style="cyan",
        padding=(1, 2),
    ))

    # Step 1: Check/install playwright
    status = check_browser_installed()

    if not status["playwright_installed"]:
        con.print("\n[bold]Installing playwright...[/]")
        try:
            subprocess.run(
                [sys.executable, "-m", "pip", "install", "playwright>=1.40"],
                check=True,
                capture_output=True,
            )
            con.print("[green]✓ Playwright installed[/]")
        except subprocess.CalledProcessError as e:
            con.print(f"[red]✗ Failed to install playwright: {e.stderr.decode()[:200]}[/]")
            return False
    else:
        con.print("[green]✓ Playwright already installed[/]")

    # Step 2: Install Chromium
    if not status["chromium_installed"]:
        con.print("\n[bold]Installing Chromium...[/]")
        with con.status("[bold cyan]Downloading Chromium...", spinner="dots"):
            try:
                subprocess.run(
                    [sys.executable, "-m", "playwright", "install", "chromium"],
                    check=True,
                    capture_output=True,
                )
                con.print("[green]✓ Chromium installed[/]")
            except subprocess.CalledProcessError as e:
                con.print(f"[red]✗ Failed to install Chromium: {e.stderr.decode()[:200]}[/]")
                return False
    else:
        con.print("[green]✓ Chromium already installed[/]")

    # Step 3: Test
    con.print("\n[bold]Testing browser...[/]")
    with con.status("[bold cyan]Opening test page...", spinner="dots"):
        try:
            with BrowserTool() as browser:
                data = browser.quick_scrape("https://example.com")
                if data.get("title"):
                    con.print(f"[green]✓ Browser working! Page title: {data['title']}[/]")
                else:
                    con.print("[yellow]⚠ Browser opened but page title is empty[/]")
        except Exception as e:
            con.print(f"[red]✗ Browser test failed: {e}[/]")
            return False

    # Save config
    cfg = _load_config()
    cfg["browser_installed"] = True
    _save_config(cfg)

    con.print(Panel(
        "[bold green]Browser ready![/]\n\n"
        "[dim]Skills can now:[/]\n"
        "  from alive.integrations.browser import BrowserTool\n"
        "  with BrowserTool() as browser:\n"
        '      data = browser.quick_scrape("https://example.com")',
        title="[bold green]Setup Complete[/]",
        border_style="green",
        padding=(1, 2),
    ))
    return True


def test_browser(console=None) -> bool:
    """Run a test browser scrape and display results."""
    from rich.console import Console
    from rich.panel import Panel

    con = console or Console()
    con.print("[bold cyan]Testing browser...[/]\n")

    status = check_browser_installed()
    if not status["playwright_installed"]:
        con.print("[red]Playwright not installed. Run: alive setup browser[/]")
        return False

    try:
        with BrowserTool() as browser:
            data = browser.quick_scrape("https://example.com")
            con.print(Panel(
                f"[bold]Title:[/] {data['title']}\n"
                f"[bold]Text:[/] {data['text'][:200]}...\n"
                f"[bold]URL:[/] {data['url']}",
                title="[bold green]Browser Test OK[/]",
                border_style="green",
            ))
            return True
    except Exception as e:
        con.print(f"[bold red]✗ Browser test failed: {e}[/]")
        return False


# Need sys for setup
import sys  # noqa: E402
