"""
Sessão única Playwright + visão de ecrã (Grok Vision) para POST /command.
Padrão tipo computer use: browser controlado pelo agente + percepção do desktop.
"""

from __future__ import annotations

import asyncio
from typing import Any, Awaitable, Callable

from .agent_browser_controller import BrowserController

_PACKAGE_DIR = __import__("pathlib").Path(__file__).resolve().parent

_cb_lock = asyncio.Lock()
_computer_browser: BrowserController | None = None


def browser_session_active() -> bool:
    return _computer_browser is not None


def _p(params: dict[str, Any], *keys: str, default: Any = None) -> Any:
    for k in keys:
        if k in params and params[k] is not None:
            return params[k]
    return default


async def computer_browser_start(params: dict[str, Any]) -> dict[str, Any]:
    global _computer_browser
    headless = bool(_p(params, "headless", default=False))
    slow_mo = int(_p(params, "slow_mo", "slowmo", default=50))
    async with _cb_lock:
        if _computer_browser is not None:
            return {
                "success": True,
                "action": "computer_browser_start",
                "already_running": True,
                "hint": "Sessão já ativa. Use computer_browser_stop para reiniciar com outras opções.",
            }
        sd = str(_PACKAGE_DIR / ".ad06_cache" / "browser")
        bc = BrowserController(screenshot_dir=sd, headless=headless, slow_mo=slow_mo)
        await bc.start()
        _computer_browser = bc
    return {"success": True, "action": "computer_browser_start", "headless": headless, "slow_mo": slow_mo}


async def computer_browser_stop(_params: dict[str, Any]) -> dict[str, Any]:
    global _computer_browser
    async with _cb_lock:
        if _computer_browser is None:
            return {"success": True, "action": "computer_browser_stop", "note": "nenhuma sessão ativa"}
        await _computer_browser.stop()
        _computer_browser = None
    return {"success": True, "action": "computer_browser_stop"}


async def computer_browser_state(_params: dict[str, Any]) -> dict[str, Any]:
    async with _cb_lock:
        if _computer_browser is None:
            return {"success": True, "action": "computer_browser_state", "active": False}
        url = await _computer_browser.get_current_url()
        title = await _computer_browser.get_title()
        return {
            "success": True,
            "action": "computer_browser_state",
            "active": True,
            "url": url,
            "title": title,
        }


async def _run_locked(coro_factory: Callable[[BrowserController], Awaitable[dict[str, Any]]]) -> dict[str, Any]:
    async with _cb_lock:
        if _computer_browser is None:
            return {
                "success": False,
                "error": "no_browser_session",
                "hint": "computer_browser_start primeiro.",
            }
        b = _computer_browser
        try:
            return await coro_factory(b)
        except Exception as exc:
            return {"success": False, "error": str(exc), "action": "computer_browser"}


async def computer_browser_goto(params: dict[str, Any]) -> dict[str, Any]:
    url = str(_p(params, "url", default="")).strip()
    if not url:
        return {"success": False, "error": "missing_url"}

    async def _go(b: BrowserController) -> dict[str, Any]:
        await b.goto(url)
        return {
            "success": True,
            "action": "computer_browser_goto",
            "url": await b.get_current_url(),
            "title": await b.get_title(),
        }

    return await _run_locked(_go)


async def computer_browser_summary(_params: dict[str, Any]) -> dict[str, Any]:
    async def _sum(b: BrowserController) -> dict[str, Any]:
        s = await b.get_page_summary()
        return {"success": True, "action": "computer_browser_summary", "summary": s}

    return await _run_locked(_sum)


async def computer_browser_click_text(params: dict[str, Any]) -> dict[str, Any]:
    text = str(_p(params, "text", "match_text", default="")).strip()
    if not text:
        return {"success": False, "error": "missing_text"}

    async def _c(b: BrowserController) -> dict[str, Any]:
        ok = await b.click_text(text, exact=bool(_p(params, "exact", default=False)))
        return {"success": ok, "action": "computer_browser_click_text", "text": text}

    return await _run_locked(_c)


async def computer_browser_click_link(params: dict[str, Any]) -> dict[str, Any]:
    text = str(_p(params, "text", "link_text", default="")).strip()
    if not text:
        return {"success": False, "error": "missing_text"}

    async def _c(b: BrowserController) -> dict[str, Any]:
        ok = await b.click_link(text)
        return {"success": ok, "action": "computer_browser_click_link", "text": text}

    return await _run_locked(_c)


async def computer_browser_click_selector(params: dict[str, Any]) -> dict[str, Any]:
    sel = str(_p(params, "selector", default="")).strip()
    if not sel:
        return {"success": False, "error": "missing_selector"}

    async def _c(b: BrowserController) -> dict[str, Any]:
        ok = await b.click_selector(sel)
        return {"success": ok, "action": "computer_browser_click_selector", "selector": sel}

    return await _run_locked(_c)


async def computer_browser_click_href(params: dict[str, Any]) -> dict[str, Any]:
    part = str(_p(params, "href", "href_contains", default="")).strip()
    if not part:
        return {"success": False, "error": "missing_href"}

    async def _c(b: BrowserController) -> dict[str, Any]:
        ok = await b.click_link_by_href(part)
        return {"success": ok, "action": "computer_browser_click_href", "href_contains": part}

    return await _run_locked(_c)


async def computer_browser_fill(params: dict[str, Any]) -> dict[str, Any]:
    sel = str(_p(params, "selector", default="")).strip()
    text = str(_p(params, "text", "value", default=""))
    if not sel:
        return {"success": False, "error": "missing_selector"}

    async def _c(b: BrowserController) -> dict[str, Any]:
        ok = await b.type_in(sel, text, clear_first=bool(_p(params, "clear_first", default=True)))
        return {"success": ok, "action": "computer_browser_fill", "selector": sel}

    return await _run_locked(_c)


async def computer_browser_scroll(params: dict[str, Any]) -> dict[str, Any]:
    direction = str(_p(params, "direction", "direcao", default="down")).lower().strip()
    pixels = int(_p(params, "pixels", "amount", default=500))

    async def _c(b: BrowserController) -> dict[str, Any]:
        if direction in ("down", "baixo"):
            await b.scroll_down(pixels)
        elif direction in ("up", "cima"):
            await b.scroll_up(pixels)
        elif direction in ("bottom", "fim", "end"):
            await b.scroll_to_bottom()
        elif direction in ("top", "topo", "start"):
            await b.scroll_to_top()
        else:
            await b.scroll_down(pixels)
        return {"success": True, "action": "computer_browser_scroll", "direction": direction}

    return await _run_locked(_c)


async def computer_browser_google(params: dict[str, Any]) -> dict[str, Any]:
    q = str(_p(params, "query", "q", default="")).strip()
    if not q:
        return {"success": False, "error": "missing_query"}

    async def _c(b: BrowserController) -> dict[str, Any]:
        await b.search_google(q)
        return {
            "success": True,
            "action": "computer_browser_google",
            "url": await b.get_current_url(),
            "title": await b.get_title(),
        }

    return await _run_locked(_c)


async def computer_browser_press_key(params: dict[str, Any]) -> dict[str, Any]:
    key = str(_p(params, "key", "tecla", default="")).strip()
    if not key:
        return {"success": False, "error": "missing_key"}

    async def _c(b: BrowserController) -> dict[str, Any]:
        await b.press_key(key)
        return {"success": True, "action": "computer_browser_press_key", "key": key}

    return await _run_locked(_c)


async def computer_browser_screenshot(params: dict[str, Any]) -> dict[str, Any]:
    full = bool(_p(params, "full_page", default=False))

    async def _c(b: BrowserController) -> dict[str, Any]:
        b64 = await b.screenshot_as_base64(full_page=full)
        return {"success": True, "action": "computer_browser_screenshot", "image_base64": b64, "mime": "image/png"}

    return await _run_locked(_c)


def vision_available() -> bool:
    from .agent_vision_loop import resolve_xai_api_key

    return resolve_xai_api_key() is not None


def _vision_loop():
    from .agent_vision_loop import VisionLoop

    return VisionLoop()


def _region_from_params(params: dict[str, Any]) -> tuple[int, int, int, int] | None:
    x = _p(params, "region_x", "x", default=None)
    y = _p(params, "region_y", "y", default=None)
    w = _p(params, "region_w", "width", default=None)
    h = _p(params, "region_h", "height", default=None)
    if x is None or y is None or w is None or h is None:
        return None
    xi, yi, wi, hi = int(x), int(y), int(w), int(h)
    if wi <= 0 or hi <= 0:
        return None
    return (xi, yi, wi, hi)


async def computer_screen_ask(params: dict[str, Any]) -> dict[str, Any]:
    question = str(_p(params, "question", "pergunta", "q", default="")).strip()
    if not question:
        return {"success": False, "error": "missing_question"}
    if not vision_available():
        return {
            "success": False,
            "error": "vision_no_api_key",
            "hint": "Defina XAI_API_KEY ou GROK_API_KEY para computer_screen_*.",
        }
    region = _region_from_params(params)
    vl = _vision_loop()

    def _call() -> str:
        return vl.ver_tela(question, region=region)

    try:
        answer = await asyncio.to_thread(_call)
        return {"success": True, "action": "computer_screen_ask", "answer": answer}
    except Exception as exc:
        return {"success": False, "error": str(exc), "action": "computer_screen_ask"}


async def computer_screen_describe(_params: dict[str, Any]) -> dict[str, Any]:
    if not vision_available():
        return {"success": False, "error": "vision_no_api_key", "hint": "XAI_API_KEY ou GROK_API_KEY"}
    vl = _vision_loop()

    def _call() -> str:
        return vl.descrever_tela_completa()

    try:
        answer = await asyncio.to_thread(_call)
        return {"success": True, "action": "computer_screen_describe", "answer": answer}
    except Exception as exc:
        return {"success": False, "error": str(exc)}


async def computer_screen_find_click(params: dict[str, Any]) -> dict[str, Any]:
    desc = str(_p(params, "description", "descricao", "target", default="")).strip()
    if not desc:
        return {"success": False, "error": "missing_description"}
    if not vision_available():
        return {"success": False, "error": "vision_no_api_key"}
    vl = _vision_loop()

    def _call() -> bool:
        return vl.ver_e_clicar(desc)

    try:
        ok = await asyncio.to_thread(_call)
        return {"success": ok, "action": "computer_screen_find_click", "clicked": ok, "target": desc}
    except Exception as exc:
        return {"success": False, "error": str(exc)}


async def computer_use_run(params: dict[str, Any]) -> dict[str, Any]:
    objetivo = str(_p(params, "objective", "objetivo", "goal", default="")).strip()
    if not objetivo:
        return {"success": False, "error": "missing_objective"}
    if not vision_available():
        return {"success": False, "error": "vision_no_api_key"}
    max_steps = min(12, max(1, int(_p(params, "max_steps", default=6))))
    vl = _vision_loop()

    def _call() -> dict[str, Any]:
        return vl.executar_tarefa(objetivo, max_steps=max_steps)

    try:
        out = await asyncio.to_thread(_call)
        return {"success": True, "action": "computer_use_run", **out}
    except Exception as exc:
        return {"success": False, "error": str(exc), "action": "computer_use_run"}


COMPUTER_HANDLERS: dict[str, Callable[[dict[str, Any]], Awaitable[dict[str, Any]]]] = {
    "computer_browser_start": computer_browser_start,
    "computer_browser_stop": computer_browser_stop,
    "computer_browser_state": computer_browser_state,
    "computer_browser_goto": computer_browser_goto,
    "computer_browser_summary": computer_browser_summary,
    "computer_browser_click_text": computer_browser_click_text,
    "computer_browser_click_link": computer_browser_click_link,
    "computer_browser_click_selector": computer_browser_click_selector,
    "computer_browser_click_href": computer_browser_click_href,
    "computer_browser_fill": computer_browser_fill,
    "computer_browser_scroll": computer_browser_scroll,
    "computer_browser_google": computer_browser_google,
    "computer_browser_press_key": computer_browser_press_key,
    "computer_browser_screenshot": computer_browser_screenshot,
    "computer_screen_ask": computer_screen_ask,
    "computer_screen_describe": computer_screen_describe,
    "computer_screen_find_click": computer_screen_find_click,
    "computer_use_run": computer_use_run,
}
