"""
Module: sandbox.backends.http
Description: Local HTTP backend that executes requests via httpx.

Implements:
    - docs/cli/reference.md#huitzo-dev
    - docs/guides/developer-environment.md#development-session-flow

See Also:
    - docs/sdk/integrations.md#http-integration
"""

from __future__ import annotations

import asyncio
from typing import Any

import httpx

from huitzo_sdk.errors import HTTPError


class LocalHTTPBackend:
    """Local HTTP backend for sandbox development.

    Satisfies the huitzo_sdk HTTPBackend protocol.
    """

    def __init__(self) -> None:
        self._client: httpx.AsyncClient | None = None
        self._lock = asyncio.Lock()

    async def _get_client(self) -> httpx.AsyncClient:
        if self._client is None:
            async with self._lock:
                if self._client is None:
                    self._client = httpx.AsyncClient(
                        timeout=30.0,
                        follow_redirects=True,
                    )
        return self._client

    async def request(
        self,
        method: str,
        url: str,
        *,
        headers: dict[str, str] | None,
        params: dict[str, Any] | None,
        json: Any | None,
        data: dict[str, Any] | None,
        files: dict[str, bytes] | None,
        timeout: int | None,
    ) -> Any:
        client = await self._get_client()

        kwargs: dict[str, Any] = {"method": method, "url": url}
        if headers:
            kwargs["headers"] = headers
        if params:
            kwargs["params"] = params
        if json is not None:
            kwargs["json"] = json
        if data is not None:
            kwargs["data"] = data
        if files is not None:
            kwargs["files"] = {k: ("file", v) for k, v in files.items()}
        if timeout is not None:
            kwargs["timeout"] = float(timeout)

        try:
            resp = await client.request(**kwargs)
            resp.raise_for_status()
        except httpx.HTTPStatusError as exc:
            raise HTTPError(
                url=url,
                method=method,
                status_code=exc.response.status_code,
                response_body=exc.response.text[:200],
                message=f"HTTP {exc.response.status_code} from {method} {url}",
            ) from exc
        except httpx.RequestError as exc:
            raise HTTPError(
                url=url,
                method=method,
                message=f"Request failed: {exc}",
            ) from exc

        content_type = resp.headers.get("content-type", "")
        if "application/json" in content_type:
            return resp.json()
        return resp.text
