"""Async HTTP-Client für die Gamma.app API v1.0."""

from __future__ import annotations

import asyncio
import os

import httpx

BASE_URL = "https://public-api.gamma.app/v1.0/"

_ERROR_MESSAGES: dict[int, str] = {
    400: "Ungültige Anfrage. Prüfen Sie die übergebenen Parameter.",
    401: "Ungültiger API-Key. Prüfen Sie die Umgebungsvariable GAMMA_API_KEY.",
    403: (
        "Zugriff verweigert — keine Credits oder fehlendes Abo. "
        "Prüfen Sie gamma.app/settings/billing."
    ),
    429: "Rate Limit erreicht. Bitte warten Sie einen Moment.",
}


class GammaAPIError(Exception):
    """Fehler bei der Kommunikation mit der Gamma API."""

    def __init__(self, status_code: int, message: str) -> None:
        self.status_code = status_code
        self.message = message
        super().__init__(message)


class GammaClient:
    """Async HTTP-Client für alle Gamma API v1.0 Endpoints."""

    def __init__(self) -> None:
        self._client: httpx.AsyncClient | None = None

    def _ensure_client(self) -> httpx.AsyncClient:
        if self._client is None:
            api_key = os.environ.get("GAMMA_API_KEY", "")
            self._client = httpx.AsyncClient(
                base_url=BASE_URL,
                headers={
                    "X-API-KEY": api_key,
                    "Content-Type": "application/json",
                    "Accept": "application/json",
                },
                timeout=30.0,
            )
        return self._client

    def _handle_response(self, response: httpx.Response) -> dict:
        if response.is_success:
            return response.json()

        status = response.status_code

        if status == 400:
            detail = ""
            try:
                body = response.json()
                detail = body.get("message") or body.get("detail") or str(body)
            except Exception:
                detail = response.text
            msg = f"Ungültige Anfrage. {detail}"
        elif status in _ERROR_MESSAGES:
            msg = _ERROR_MESSAGES[status]
        elif status == 422:
            detail = ""
            try:
                body = response.json()
                detail = body.get("detail") or body.get("message") or str(body)
            except Exception:
                detail = response.text
            msg = f"Ungültige Parameter. {detail}"
        else:
            detail = ""
            try:
                body = response.json()
                detail = body.get("detail") or body.get("message") or str(body)
            except Exception:
                detail = response.text
            msg = f"Unerwarteter Fehler ({status}). {detail}"

        raise GammaAPIError(status, msg)

    # ------------------------------------------------------------------ #
    # API methods
    # ------------------------------------------------------------------ #

    async def generate(self, payload: dict) -> dict:
        """POST /generations — erstellt eine neue Gamma."""
        client = self._ensure_client()
        resp = await client.post("generations", json=payload)
        return self._handle_response(resp)

    async def generate_from_template(self, payload: dict) -> dict:
        """POST /generations/from-template — erstellt Gamma aus Vorlage."""
        client = self._ensure_client()
        resp = await client.post("generations/from-template", json=payload)
        return self._handle_response(resp)

    async def get_generation(self, generation_id: str) -> dict:
        """GET /generations/{id} — ruft den Status einer Generation ab."""
        client = self._ensure_client()
        resp = await client.get(f"generations/{generation_id}")
        return self._handle_response(resp)

    async def poll_generation(
        self,
        generation_id: str,
        max_wait: int = 300,
    ) -> dict:
        """Pollt GET /generations/{id} alle 5 s bis completed/failed/timeout."""
        elapsed = 0
        while elapsed < max_wait:
            result = await self.get_generation(generation_id)
            status = result.get("status")
            if status in ("completed", "failed"):
                return result
            await asyncio.sleep(5)
            elapsed += 5

        return {
            "generationId": generation_id,
            "status": "timeout",
            "_hinweis": (
                f"Kein Ergebnis nach {max_wait} Sekunden. "
                "Versuchen Sie gamma_status_abrufen erneut."
            ),
        }

    async def list_themes(
        self,
        limit: int = 50,
        after: str | None = None,
    ) -> dict:
        """GET /themes — listet verfügbare Themes."""
        params: dict[str, str | int] = {"limit": limit}
        if after:
            params["after"] = after

        client = self._ensure_client()
        resp = await client.get("themes", params=params)
        return self._handle_response(resp)

    async def list_folders(
        self,
        limit: int = 50,
        after: str | None = None,
    ) -> dict:
        """GET /folders — listet Workspace-Ordner."""
        params: dict[str, str | int] = {"limit": limit}
        if after:
            params["after"] = after

        client = self._ensure_client()
        resp = await client.get("folders", params=params)
        return self._handle_response(resp)

    async def close(self) -> None:
        """Schliesst den HTTP-Client."""
        if self._client is not None:
            await self._client.aclose()
            self._client = None
