"""Thin HTTP client that targets the Partner Ecosystem API.

Authenticates every call with the project credentials (HTTP Basic) and tags it
with the ``x-project-id`` header, mirroring the Node SDK.
"""

from __future__ import annotations

import base64
from typing import Any, Mapping, Optional

import httpx

from .config import ResolvedConfig
from .errors import ApiError


class HttpClient:
    def __init__(self, config: ResolvedConfig) -> None:
        self._config = config
        token = base64.b64encode(
            f"{config.project_id}:{config.project_secret}".encode("utf-8")
        ).decode("ascii")
        self._auth_header = f"Basic {token}"
        self._client = httpx.Client(base_url=config.api_url + "/")

    def request(
        self,
        path: str,
        *,
        method: str = "GET",
        body: Any = None,
        query: Optional[Mapping[str, Any]] = None,
        headers: Optional[Mapping[str, str]] = None,
    ) -> Any:
        params = None
        if query:
            params = {k: str(v) for k, v in query.items() if v is not None}

        request_headers: dict[str, str] = {
            "accept": "application/json",
            "authorization": self._auth_header,
            "x-project-id": self._config.project_id,
        }
        if headers:
            request_headers.update({k: v for k, v in headers.items() if v is not None})

        response = self._client.request(
            method,
            path.lstrip("/"),
            params=params,
            json=body if body is not None else None,
            headers=request_headers,
        )

        payload = _parse_body(response)

        if response.is_error:
            message = None
            if isinstance(payload, Mapping) and isinstance(payload.get("message"), str):
                message = payload["message"]
            if not message:
                message = (
                    f"Request to {path} failed with status {response.status_code}"
                )
            raise ApiError(message, response.status_code, payload)

        return payload

    def close(self) -> None:
        self._client.close()


def _parse_body(response: httpx.Response) -> Any:
    text = response.text
    if not text:
        return None
    content_type = response.headers.get("content-type", "")
    if "application/json" in content_type:
        try:
            return response.json()
        except ValueError:
            return text
    return text
