"""Base HTTP client for Purple Flea API services."""

from __future__ import annotations

import time
from typing import Any

import requests


class PurpleFleaClient:
    """Low-level HTTP client shared by all service clients."""

    BASE_URL = "https://api.purpleflea.com"

    def __init__(
        self,
        api_key: str,
        base_url: str | None = None,
        timeout: float = 30.0,
        max_retries: int = 3,
    ) -> None:
        self.api_key = api_key
        self.base_url = (base_url or self.BASE_URL).rstrip("/")
        self.timeout = timeout
        self.max_retries = max_retries
        self.session = requests.Session()
        self.session.headers.update(
            {
                "Authorization": f"Bearer {api_key}",
                "Content-Type": "application/json",
                "Accept": "application/json",
            }
        )

    # -- helpers -------------------------------------------------------------

    def _url(self, path: str) -> str:
        return f"{self.base_url}/{path.lstrip('/')}"

    def _request(
        self,
        method: str,
        path: str,
        params: dict[str, Any] | None = None,
        json: dict[str, Any] | None = None,
    ) -> dict[str, Any]:
        url = self._url(path)
        last_exc: Exception | None = None

        for attempt in range(1, self.max_retries + 1):
            try:
                resp = self.session.request(
                    method, url, params=params, json=json, timeout=self.timeout
                )
                resp.raise_for_status()
                return resp.json()
            except requests.exceptions.HTTPError as exc:
                status = exc.response.status_code if exc.response is not None else None
                if status is not None and status < 500:
                    raise APIError(status, exc.response.text) from exc
                last_exc = exc
            except requests.exceptions.ConnectionError as exc:
                last_exc = exc

            if attempt < self.max_retries:
                time.sleep(min(2**attempt, 8))

        raise APIError(None, f"Request failed after {self.max_retries} retries") from last_exc

    def get(self, path: str, **params: Any) -> dict[str, Any]:
        return self._request("GET", path, params=params or None)

    def post(self, path: str, **json_body: Any) -> dict[str, Any]:
        return self._request("POST", path, json=json_body or None)

    def put(self, path: str, **json_body: Any) -> dict[str, Any]:
        return self._request("PUT", path, json=json_body or None)

    def delete(self, path: str, **params: Any) -> dict[str, Any]:
        return self._request("DELETE", path, params=params or None)

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

    def __enter__(self) -> PurpleFleaClient:
        return self

    def __exit__(self, *args: object) -> None:
        self.close()


class APIError(Exception):
    """Raised when the Purple Flea API returns an error."""

    def __init__(self, status_code: int | None, message: str) -> None:
        self.status_code = status_code
        self.message = message
        super().__init__(f"[{status_code}] {message}")
