"""
Marziel AI — Browser Control

Provides headless browser automation for the ReAct agent.
Uses Playwright for navigation, clicking, typing, and content extraction.

Auto-captures screenshots after every action for live browser view.
Lazy-loads browser on first use, reuses instance across calls.
"""

import logging
import threading
import time
import os
import base64

logger = logging.getLogger("marziel.browser")

# ── Config ──
SCREENSHOT_DIR = "/tmp/marziel_browser"
os.makedirs(SCREENSHOT_DIR, exist_ok=True)

# ── Lazy browser singleton ──
_browser = None
_page = None
_lock = threading.Lock()
_screenshot_counter = 0
_browser_state = {
    "active": False,
    "url": "",
    "title": "",
    "last_action": "",
    "last_screenshot": "",
    "screenshot_b64": "",
    "started_at": None,
}


def get_browser_state() -> dict:
    """Return current browser state for the frontend."""
    return dict(_browser_state)


def _ensure_browser():
    """Lazy-initialize Playwright browser and page."""
    global _browser, _page
    if _page is not None:
        return _page

    with _lock:
        if _page is not None:
            return _page
        try:
            from playwright.sync_api import sync_playwright
            pw = sync_playwright().start()
            try:
                _browser = pw.chromium.launch(headless=True)
            except Exception:
                # Chromium not installed — ask user
                print()
                print("  🌐 Browser tool requires Chromium (one-time ~150 MB download).")
                answer = input("     Install now? [Y/n] ").strip().lower()
                if answer in ("", "y", "yes"):
                    import subprocess, sys
                    print("     📦 Installing Chromium...")
                    subprocess.run(
                        [sys.executable, "-m", "playwright", "install", "chromium"],
                    )
                    print("     ✅ Chromium installed")
                    _browser = pw.chromium.launch(headless=True)
                else:
                    raise RuntimeError("Chromium not installed. Browser tool unavailable.")

            _page = _browser.new_page(viewport={"width": 1280, "height": 720})
            _page.set_default_timeout(15000)
            _browser_state["active"] = True
            _browser_state["started_at"] = time.time()
            logger.info("🌐 Browser started (headless Chromium 1280x720)")
            return _page
        except ImportError:
            raise RuntimeError(
                "Playwright not installed. Run: pip install playwright"
            )
        except Exception as e:
            raise RuntimeError(f"Browser launch failed: {e}")


def _auto_screenshot(action_label: str = "") -> str:
    """Take a screenshot after every action and update state."""
    global _screenshot_counter
    if _page is None:
        return ""
    try:
        _screenshot_counter += 1
        filename = f"step_{_screenshot_counter:03d}.png"
        filepath = os.path.join(SCREENSHOT_DIR, filename)
        _page.screenshot(path=filepath, full_page=False)

        # Also get base64 for inline display
        with open(filepath, "rb") as f:
            b64 = base64.b64encode(f.read()).decode()

        _browser_state["url"] = _page.url
        _browser_state["title"] = _page.title()
        _browser_state["last_action"] = action_label
        _browser_state["last_screenshot"] = filepath
        _browser_state["screenshot_b64"] = b64

        return filepath
    except Exception as e:
        logger.warning(f"Auto-screenshot failed: {e}")
        return ""


def get_latest_screenshot_b64() -> str:
    """Return the latest screenshot as base64 PNG."""
    return _browser_state.get("screenshot_b64", "")


def browser_navigate(url: str) -> dict:
    """Navigate to a URL and return page title + text content."""
    try:
        page = _ensure_browser()
        page.goto(url, wait_until="domcontentloaded", timeout=20000)
        title = page.title()
        text = page.inner_text("body")[:3000]
        current_url = page.url
        screenshot = _auto_screenshot(f"navigate → {url}")
        return {
            "title": title,
            "url": current_url,
            "text": text,
            "screenshot": screenshot,
        }
    except Exception as e:
        return {"error": str(e)}


def browser_click(selector: str) -> dict:
    """Click an element on the current page."""
    try:
        page = _ensure_browser()
        page.click(selector, timeout=5000)
        page.wait_for_load_state("domcontentloaded", timeout=5000)
        title = page.title()
        screenshot = _auto_screenshot(f"click → {selector}")
        return {"clicked": selector, "title": title, "url": page.url, "screenshot": screenshot}
    except Exception as e:
        return {"error": f"Click failed on '{selector}': {e}"}


def browser_type(selector: str, text: str) -> dict:
    """Type text into an input field."""
    try:
        page = _ensure_browser()
        page.fill(selector, text, timeout=5000)
        screenshot = _auto_screenshot(f"type → {selector}")
        return {"typed": text, "into": selector, "screenshot": screenshot}
    except Exception as e:
        return {"error": f"Type failed on '{selector}': {e}"}


def browser_read() -> dict:
    """Read the current page content."""
    try:
        page = _ensure_browser()
        title = page.title()
        text = page.inner_text("body")[:3000]
        url = page.url
        links = page.eval_on_selector_all(
            "a[href]",
            "els => els.slice(0, 15).map(e => ({text: e.innerText.trim().slice(0, 60), href: e.href}))"
        )
        link_text = "\n".join(
            f"  [{l['text']}]({l['href']})" for l in links if l["text"]
        )
        screenshot = _auto_screenshot("read page")
        return {
            "title": title,
            "url": url,
            "text": text,
            "links": link_text,
            "screenshot": screenshot,
        }
    except Exception as e:
        return {"error": str(e)}


def browser_screenshot() -> dict:
    """Take a screenshot of the current page."""
    try:
        page = _ensure_browser()
        path = _auto_screenshot("manual screenshot")
        return {"screenshot": path, "url": page.url, "title": page.title()}
    except Exception as e:
        return {"error": str(e)}


def close_browser():
    """Close browser and free resources."""
    global _browser, _page, _screenshot_counter
    try:
        if _page:
            _page.close()
        if _browser:
            _browser.close()
        _page = None
        _browser = None
        _screenshot_counter = 0
        _browser_state.update({
            "active": False, "url": "", "title": "",
            "last_action": "", "last_screenshot": "",
            "screenshot_b64": "", "started_at": None,
        })
        logger.info("🌐 Browser closed")
    except Exception:
        pass


def execute_browser_action(action: str, parsed: dict) -> tuple:
    """
    Execute a browser action based on the parsed command.
    Returns (description, result_text) or (None, None).
    """
    command = parsed.get("command", "").strip()
    if not command:
        return None, None

    parts = command.split(maxsplit=1)
    sub_action = parts[0].lower() if parts else ""
    arg = parts[1] if len(parts) > 1 else ""

    if sub_action in ("navigate", "goto", "open", "go", "visit", "url"):
        if not arg:
            return None, None
        url = arg if arg.startswith("http") else f"https://{arg}"
        desc = f"🌐 Navigating to: {url}"
        result = browser_navigate(url)
        if result.get("error"):
            return desc, f"Error: {result['error']}"
        text_preview = result["text"][:1500]
        return desc, f"Page: {result['title']}\nURL: {result['url']}\n\nContent:\n{text_preview}"

    elif sub_action in ("click", "press", "tap"):
        if not arg:
            return None, None
        desc = f"🖱️ Clicking: {arg}"
        result = browser_click(arg)
        if result.get("error"):
            return desc, f"Error: {result['error']}"
        return desc, f"Clicked '{arg}'. Now on: {result['title']} ({result['url']})"

    elif sub_action in ("type", "fill", "input", "enter"):
        type_parts = arg.split(maxsplit=1)
        if len(type_parts) < 2:
            return None, None
        selector, text = type_parts
        desc = f"⌨️ Typing into: {selector}"
        result = browser_type(selector, text)
        if result.get("error"):
            return desc, f"Error: {result['error']}"
        return desc, f"Typed '{text}' into '{selector}'"

    elif sub_action in ("read", "content", "text", "page"):
        desc = "📄 Reading current page"
        result = browser_read()
        if result.get("error"):
            return desc, f"Error: {result['error']}"
        out = f"Page: {result['title']}\nURL: {result['url']}\n\nContent:\n{result['text'][:1500]}"
        if result.get("links"):
            out += f"\n\nLinks:\n{result['links']}"
        return desc, out

    elif sub_action in ("screenshot", "capture", "snap"):
        desc = "📸 Taking screenshot"
        result = browser_screenshot()
        if result.get("error"):
            return desc, f"Error: {result['error']}"
        return desc, f"Screenshot saved to {result['screenshot']} (Page: {result['title']})"

    elif sub_action in ("close", "quit", "exit"):
        close_browser()
        return "🌐 Closing browser", "Browser closed."

    else:
        if "." in command and " " not in command:
            url = command if command.startswith("http") else f"https://{command}"
            desc = f"🌐 Navigating to: {url}"
            result = browser_navigate(url)
            if result.get("error"):
                return desc, f"Error: {result['error']}"
            text_preview = result["text"][:1500]
            return desc, f"Page: {result['title']}\nURL: {result['url']}\n\nContent:\n{text_preview}"

    return None, None
