"""High-level browser automation manager for AiCippy."""

from __future__ import annotations

import asyncio
import contextlib
import logging
from typing import Any

from aicippy.browser.server import BrowserServer

logger = logging.getLogger(__name__)


class BrowserManager:
    """Manages browser automation via the local WebSocket server."""

    def __init__(self, server: BrowserServer) -> None:  # noqa: D107
        self._server = server

    async def capture_screenshot(self) -> str:
        """Capture a screenshot of the active tab."""
        response = await self._send_and_wait("CAPTURE_TAB_SCREENSHOT")
        return response.get("dataUrl", "")

    async def get_page_content(self) -> str:
        """Get the HTML content of the active tab."""
        response = await self._send_and_wait("PAGE_ACTION", {"action": "GET_CONTENT"})
        return response.get("content", "")

    async def execute_script(self, script: str) -> Any:  # noqa: ANN401
        """Execute JavaScript in the active tab."""
        response = await self._send_and_wait("PAGE_ACTION", {"action": "EXECUTE_SCRIPT", "script": script})
        return response.get("result")

    async def fill_form(self, selectors_and_values: dict[str, str]) -> bool:
        """Fill a form with the provided values."""
        response = await self._send_and_wait("PAGE_ACTION", {"action": "FILL_FORM", "data": selectors_and_values})
        return response.get("success", False)

    async def click_element(self, selector: str) -> bool:
        """Click an element on the page."""
        response = await self._send_and_wait("PAGE_ACTION", {"action": "CLICK", "selector": selector})
        return response.get("success", False)

    async def _send_and_wait(self, action: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
        """Send a message to the browser and wait for a response."""
        if not self._server.clients:
            raise RuntimeError("Browser extension not connected. Please enable AiCippy extension.")  # noqa: TRY003

        request_id = str(asyncio.get_running_loop().time())
        message = {
            "type": action,
            "payload": payload or {},
            "request_id": request_id,
        }

        # Create a future to wait for the response
        future = asyncio.get_running_loop().create_future()

        def handle_response(data: dict[str, Any]) -> None:
            if data.get("request_id") == request_id:
                future.set_result(data.get("payload", {}))

        # Register temporary handler
        self._server.on(f"{action}_RESPONSE", handle_response)

        try:
            await self._server.broadcast(message)
            return await asyncio.wait_for(future, timeout=30.0)
        finally:
            # Cleanup handler
            response_key = f"{action}_RESPONSE"
            if response_key in self._server._handlers:
                with contextlib.suppress(ValueError):
                    self._server._handlers[response_key].remove(handle_response)
