"""HTTP client — wraps httpx with auth injection and response envelope parsing."""

from __future__ import annotations

from typing import Any

import httpx

from turumba_cli.config import load_config
from turumba_cli.credentials import load_tokens
from turumba_cli.errors import TurumbaAPIError, TurumbaAuthError, TurumbaNotFoundError


class TurumbaClient:
    """HTTP client for the Turumba Gateway API."""

    def __init__(
        self,
        gateway_url: str | None = None,
        timeout: float = 30.0,
    ):
        config = load_config()
        self.gateway_url = (gateway_url or config.get("gateway_url", "")).rstrip("/")
        self.timeout = timeout

    def _get_auth_headers(self) -> dict[str, str]:
        """Get authorization headers from stored tokens."""
        tokens = load_tokens()
        if tokens is None:
            raise TurumbaAuthError()
        if tokens.is_expired:
            raise TurumbaAuthError("Token expired. Run: turumba auth login")
        return {"Authorization": f"Bearer {tokens.access_token}"}

    def _parse_response(self, response: httpx.Response) -> Any:
        """Parse API response, handling the standard envelope."""
        if response.status_code == 204:
            return None

        try:
            body = response.json()
        except Exception as exc:
            if response.is_success:
                return response.text
            raise TurumbaAPIError(
                status_code=response.status_code,
                error="parse_error",
                message=f"Could not parse response: {response.text[:200]}",
            ) from exc

        if response.status_code == 401:
            detail = body.get("detail", body.get("message", "Unauthorized"))
            raise TurumbaAuthError(f"Unauthorized: {detail}")

        if not response.is_success:
            if isinstance(body, dict) and "error" in body:
                error_cls = TurumbaNotFoundError if response.status_code == 404 else TurumbaAPIError
                if response.status_code == 404:
                    raise TurumbaNotFoundError(body.get("message", "Not found"))
                raise error_cls(
                    status_code=response.status_code,
                    error=body.get("error", "unknown"),
                    message=body.get("message", "Unknown error"),
                    details=body.get("details"),
                )
            raise TurumbaAPIError(
                status_code=response.status_code,
                error="unknown",
                message=str(body),
            )

        return body

    def request(
        self,
        method: str,
        path: str,
        *,
        auth: bool = True,
        params: dict[str, Any] | None = None,
        json_data: dict[str, Any] | None = None,
    ) -> Any:
        """Make an HTTP request to the gateway."""
        url = f"{self.gateway_url}{path}"
        headers = self._get_auth_headers() if auth else {}
        headers["Content-Type"] = "application/json"

        with httpx.Client(timeout=self.timeout) as http:
            response = http.request(
                method=method,
                url=url,
                headers=headers,
                params=params,
                json=json_data,
            )

        return self._parse_response(response)

    def list(
        self,
        path: str,
        *,
        filter_: list[str] | None = None,
        sort: list[str] | None = None,
        limit: int = 100,
        skip: int = 0,
    ) -> tuple[list[dict[str, Any]], dict[str, Any]]:
        """GET a list endpoint with pagination. Returns (data, meta)."""
        params: dict[str, Any] = {"limit": limit, "skip": skip}
        if filter_:
            params["filter"] = filter_
        if sort:
            params["sort"] = sort

        body = self.request("GET", path, params=params)

        if isinstance(body, dict):
            if "success" in body:
                return body.get("data", []), body.get("meta", {})
            if "data" in body:
                return body["data"], body.get("meta", {})

        if isinstance(body, list):
            return body, {}

        return [], {}

    def get(self, path: str, resource_id: str) -> dict[str, Any]:
        """GET a single resource by ID."""
        body = self.request("GET", f"{path}/{resource_id}")
        if isinstance(body, dict) and "data" in body:
            return body["data"]
        return body

    def create(self, path: str, data: dict[str, Any]) -> dict[str, Any]:
        """POST to create a resource."""
        body = self.request("POST", path, json_data=data)
        if isinstance(body, dict) and "data" in body:
            return body["data"]
        return body

    def update(
        self,
        path: str,
        resource_id: str,
        data: dict[str, Any],
        method: str = "PATCH",
    ) -> dict[str, Any]:
        """PATCH/PUT to update a resource."""
        body = self.request(method, f"{path}/{resource_id}", json_data=data)
        if isinstance(body, dict) and "data" in body:
            return body["data"]
        return body

    def delete(self, path: str, resource_id: str) -> None:
        """DELETE a resource."""
        self.request("DELETE", f"{path}/{resource_id}")

    def post(self, path: str, data: dict[str, Any] | None = None, *, auth: bool = True) -> Any:
        """Generic POST request."""
        return self.request("POST", path, json_data=data, auth=auth)
