from __future__ import annotations

from typing import Any

import httpx


QueryParams = dict[str, Any] | list[tuple[str, Any]]


class AdaptorHttpClient:
    """Async HTTP client shared by runtime adaptor and insight upstream calls."""

    def __init__(
        self,
        base_url: str,
        timeout: float = 30.0,
        default_headers: dict[str, str] | None = None,
    ) -> None:
        self.base_url = base_url.rstrip("/")
        self._timeout = timeout
        self._default_headers = dict(default_headers or {})
        self._client: httpx.AsyncClient | None = None

    async def _get_client(self) -> httpx.AsyncClient:
        if self._client is None:
            self._client = httpx.AsyncClient(
                base_url=self.base_url,
                timeout=self._timeout,
                headers=self._default_headers,
            )
        return self._client

    async def close(self) -> None:
        if self._client is not None:
            await self._client.aclose()
            self._client = None

    async def _request(
        self,
        method: str,
        path: str,
        *,
        params: QueryParams | None = None,
        json: Any = None,
        timeout: float | None = None,
    ) -> httpx.Response:
        client = await self._get_client()
        response = await client.request(
            method,
            path,
            params=params,
            json=json,
            timeout=timeout,
        )
        response.raise_for_status()
        return response

    async def _request_json(
        self,
        method: str,
        path: str,
        *,
        params: QueryParams | None = None,
        json: Any = None,
        timeout: float | None = None,
    ) -> Any:
        response = await self._request(
            method,
            path,
            params=params,
            json=json,
            timeout=timeout,
        )
        if getattr(response, "content", None) == b"":
            return None
        return response.json()

    async def post(
        self,
        path: str,
        json: dict[str, Any] | None = None,
        timeout: float | None = None,
    ) -> Any:
        return await self._request_json("POST", path, json=json, timeout=timeout)

    async def get(
        self,
        path: str,
        params: QueryParams | None = None,
    ) -> Any:
        return await self._request_json("GET", path, params=params)

    async def delete(self, path: str) -> Any:
        return await self._request_json("DELETE", path)

    async def list_agents(self) -> dict[str, Any]:
        payload = await self.get("/agent/list")
        return payload if isinstance(payload, dict) else {}

    async def health_check(self) -> bool:
        try:
            response = await self._request("GET", "/ping")
            return response.status_code == 200
        except Exception:
            return False