"""
Async browser session methods for Firecrawl v2 API.

Provides async create, execute, delete, and list operations for browser sessions.
"""

from typing import Any, Dict, List, Literal, Optional

from ...types import (
    BrowserCreateResponse,
    BrowserExecuteResponse,
    BrowserDeleteResponse,
    BrowserListResponse,
)
from ...utils.http_client_async import AsyncHttpClient


def _normalize_browser_create_response(payload: Dict[str, Any]) -> Dict[str, Any]:
    out = dict(payload)
    if "cdpUrl" in out and "cdp_url" not in out:
        out["cdp_url"] = out["cdpUrl"]
    if "liveViewUrl" in out and "live_view_url" not in out:
        out["live_view_url"] = out["liveViewUrl"]
    if "expiresAt" in out and "expires_at" not in out:
        out["expires_at"] = out["expiresAt"]
    return out


def _normalize_browser_list_response(payload: Dict[str, Any]) -> Dict[str, Any]:
    out = dict(payload)
    if "sessions" in out and isinstance(out["sessions"], list):
        normalized_sessions = []
        for s in out["sessions"]:
            ns = dict(s)
            if "cdpUrl" in ns and "cdp_url" not in ns:
                ns["cdp_url"] = ns["cdpUrl"]
            if "liveViewUrl" in ns and "live_view_url" not in ns:
                ns["live_view_url"] = ns["liveViewUrl"]
            if "streamWebView" in ns and "stream_web_view" not in ns:
                ns["stream_web_view"] = ns["streamWebView"]
            if "createdAt" in ns and "created_at" not in ns:
                ns["created_at"] = ns["createdAt"]
            if "lastActivity" in ns and "last_activity" not in ns:
                ns["last_activity"] = ns["lastActivity"]
            normalized_sessions.append(ns)
        out["sessions"] = normalized_sessions
    return out


async def browser(
    client: AsyncHttpClient,
    *,
    ttl: Optional[int] = None,
    activity_ttl: Optional[int] = None,
    stream_web_view: Optional[bool] = None,
) -> BrowserCreateResponse:
    """Create a new browser session.

    Args:
        client: Async HTTP client instance
        ttl: Total time-to-live in seconds (30-3600, default 300)
        activity_ttl: Inactivity TTL in seconds (10-3600)
        stream_web_view: Whether to enable webview streaming

    Returns:
        BrowserCreateResponse with session id and CDP URL
    """
    body: Dict[str, Any] = {}
    if ttl is not None:
        body["ttl"] = ttl
    if activity_ttl is not None:
        body["activityTtl"] = activity_ttl
    if stream_web_view is not None:
        body["streamWebView"] = stream_web_view

    resp = await client.post("/v2/browser", body)
    payload = _normalize_browser_create_response(resp.json())
    return BrowserCreateResponse(**payload)


def _normalize_browser_execute_response(payload: Dict[str, Any]) -> Dict[str, Any]:
    out = dict(payload)
    if "exitCode" in out and "exit_code" not in out:
        out["exit_code"] = out["exitCode"]
    return out


def _normalize_browser_delete_response(payload: Dict[str, Any]) -> Dict[str, Any]:
    out = dict(payload)
    if "sessionDurationMs" in out and "session_duration_ms" not in out:
        out["session_duration_ms"] = out["sessionDurationMs"]
    if "creditsBilled" in out and "credits_billed" not in out:
        out["credits_billed"] = out["creditsBilled"]
    return out


async def browser_execute(
    client: AsyncHttpClient,
    session_id: str,
    code: str,
    *,
    language: Literal["python", "node", "bash"] = "bash",
    timeout: Optional[int] = None,
) -> BrowserExecuteResponse:
    """Execute code in a browser session.

    Args:
        client: Async HTTP client instance
        session_id: Browser session ID
        code: Code to execute
        language: Programming language ("python", "node", or "bash")
        timeout: Execution timeout in seconds (1-300, default 30)

    Returns:
        BrowserExecuteResponse with execution result
    """
    body: Dict[str, Any] = {
        "code": code,
        "language": language,
    }
    if timeout is not None:
        body["timeout"] = timeout

    resp = await client.post(f"/v2/browser/{session_id}/execute", body)
    payload = _normalize_browser_execute_response(resp.json())
    return BrowserExecuteResponse(**payload)


async def delete_browser(
    client: AsyncHttpClient,
    session_id: str,
) -> BrowserDeleteResponse:
    """Delete a browser session.

    Args:
        client: Async HTTP client instance
        session_id: Browser session ID

    Returns:
        BrowserDeleteResponse
    """
    resp = await client.delete(f"/v2/browser/{session_id}")
    payload = _normalize_browser_delete_response(resp.json())
    return BrowserDeleteResponse(**payload)


async def list_browsers(
    client: AsyncHttpClient,
    *,
    status: Optional[Literal["active", "destroyed"]] = None,
) -> BrowserListResponse:
    """List browser sessions.

    Args:
        client: Async HTTP client instance
        status: Filter by session status ("active" or "destroyed")

    Returns:
        BrowserListResponse with list of sessions
    """
    endpoint = "/v2/browser"
    if status is not None:
        endpoint = f"{endpoint}?status={status}"

    resp = await client.get(endpoint)
    payload = _normalize_browser_list_response(resp.json())
    return BrowserListResponse(**payload)
