"""Shared HTTP transport and error handling."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any

import httpx


@dataclass
class APIError(Exception):
    """API error with status code and details."""

    status_code: int
    message: str
    details: dict[str, Any] = field(default_factory=dict)

    def __str__(self) -> str:
        return f"[{self.status_code}] {self.message}"


class HTTPTransport:
    """Manages an httpx.AsyncClient for SDK requests."""

    def __init__(
        self,
        api_key: str,
        base_url: str = "https://api.brehon.dev",
        timeout: float = 30.0,
    ) -> None:
        self._api_key = api_key
        self._base_url = base_url.rstrip("/")
        self._timeout = timeout
        self._client: httpx.AsyncClient | None = None

    def _get_client(self) -> httpx.AsyncClient:
        if self._client is None or self._client.is_closed:
            self._client = httpx.AsyncClient(
                base_url=f"{self._base_url}/api/v1",
                headers={
                    "Authorization": f"Bearer {self._api_key}",
                    "User-Agent": "brehon-python-sdk/1.0.0",
                },
                timeout=self._timeout,
            )
        return self._client

    async def request(
        self,
        method: str,
        path: str,
        *,
        params: dict[str, Any] | None = None,
        json: Any = None,
    ) -> Any:
        """Make an API request. Raises APIError on failure."""
        try:
            resp = await self._get_client().request(
                method, path, params=params, json=json
            )
        except httpx.HTTPError as exc:
            raise APIError(status_code=0, message=f"Request failed: {exc}") from exc

        if resp.status_code == 429:
            retry_after = resp.headers.get("Retry-After", "60")
            raise APIError(
                status_code=429,
                message=f"Rate limit exceeded. Retry after {retry_after} seconds.",
                details={"retry_after": int(retry_after)},
            )

        try:
            data = resp.json()
        except Exception:
            data = {"message": resp.text}

        if resp.is_error:
            detail = data.get("detail", f"HTTP {resp.status_code}") if isinstance(data, dict) else f"HTTP {resp.status_code}"
            raise APIError(
                status_code=resp.status_code,
                message=detail,
                details=data if isinstance(data, dict) else {},
            )

        return data

    async def close(self) -> None:
        """Close the underlying HTTP client."""
        if self._client is not None and not self._client.is_closed:
            await self._client.aclose()
            self._client = None
