"""Goodmem and AsyncGoodmem — the main entry points."""

from __future__ import annotations

import httpx

from goodmem.api.admin import AdminAPI, AsyncAdminAPI
from goodmem.api.apikeys import ApikeysAPI, AsyncApikeysAPI
from goodmem.api.embedders import AsyncEmbeddersAPI, EmbeddersAPI
from goodmem.api.llms import AsyncLlmsAPI, LlmsAPI
from goodmem.api.memories import AsyncMemoriesAPI, MemoriesAPI
from goodmem.api.ocr import AsyncOcrAPI, OcrAPI
from goodmem.api.rerankers import AsyncRerankersAPI, RerankersAPI
from goodmem.api.spaces import AsyncSpacesAPI, SpacesAPI
from goodmem.api.system import AsyncSystemAPI, SystemAPI
from goodmem.api.users import AsyncUsersAPI, UsersAPI


def _auth_headers(api_key: str) -> dict[str, str]:
    """Build auth headers from a GoodMem API key."""
    return {"x-api-key": api_key}


class Goodmem:
    """Synchronous GoodMem API client.

    Args:
        base_url (str): Base URL of the GoodMem server (e.g. ``"http://localhost:8080"``).
        api_key (str): GoodMem API key (prefix ``gm_``), sent as ``x-api-key`` header.
        timeout (float, optional): HTTP request timeout in seconds. Defaults to ``30.0``.
        **kwargs: Additional keyword arguments forwarded to ``httpx.Client``.

    Usage::

        client = Goodmem(base_url="http://localhost:8080", api_key="gm_...")

        # Or as context manager (recommended — ensures the connection pool is closed)
        with Goodmem(base_url="...", api_key="gm_...") as client:
            embedder = client.embedders.create(
                display_name="My Embedder",
                model_identifier="text-embedding-3-large",
                api_key="sk-...",
            )

    Attributes:
        embedders: :class:`~goodmem.api.embedders.EmbeddersAPI`
        rerankers: :class:`~goodmem.api.rerankers.RerankersAPI`
        llms: :class:`~goodmem.api.llms.LlmsAPI`
        spaces: :class:`~goodmem.api.spaces.SpacesAPI`
        memories: :class:`~goodmem.api.memories.MemoriesAPI`
        apikeys: :class:`~goodmem.api.apikeys.ApikeysAPI`
        users: :class:`~goodmem.api.users.UsersAPI`
        ocr: :class:`~goodmem.api.ocr.OcrAPI`
        system: :class:`~goodmem.api.system.SystemAPI`
        admin: :class:`~goodmem.api.admin.AdminAPI`
    """

    def __init__(
        self,
        base_url: str,
        api_key: str,
        *,
        timeout: float = 30.0,
        **kwargs,
    ) -> None:
        self._http = httpx.Client(base_url=base_url, timeout=timeout, **kwargs)
        self._headers = _auth_headers(api_key)

        # Namespace APIs
        self.embedders = EmbeddersAPI(self._http, self._headers)
        self.rerankers = RerankersAPI(self._http, self._headers)
        self.llms = LlmsAPI(self._http, self._headers)
        self.spaces = SpacesAPI(self._http, self._headers)
        self.memories = MemoriesAPI(self._http, self._headers)
        self.apikeys = ApikeysAPI(self._http, self._headers)
        self.users = UsersAPI(self._http, self._headers)
        self.ocr = OcrAPI(self._http, self._headers)
        self.system = SystemAPI(self._http, self._headers)
        self.admin = AdminAPI(self._http, self._headers)

    def close(self) -> None:
        """Close the underlying HTTP client."""
        self._http.close()

    def __enter__(self) -> Goodmem:
        return self

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


class AsyncGoodmem:
    """Asynchronous GoodMem API client.

    Args:
        base_url (str): Base URL of the GoodMem server.
        api_key (str): GoodMem API key (prefix ``gm_``), sent as ``x-api-key`` header.
        timeout (float, optional): HTTP request timeout in seconds. Defaults to ``30.0``.
        **kwargs: Additional keyword arguments forwarded to ``httpx.AsyncClient``.

    Usage::

        async with AsyncGoodmem(base_url="...", api_key="gm_...") as client:
            embedder = await client.embedders.create(
                display_name="My Embedder",
                model_identifier="text-embedding-3-large",
                api_key="sk-...",
            )

    Attributes:
        embedders: :class:`~goodmem.api.embedders.AsyncEmbeddersAPI`
        rerankers: :class:`~goodmem.api.rerankers.AsyncRerankersAPI`
        llms: :class:`~goodmem.api.llms.AsyncLlmsAPI`
        spaces: :class:`~goodmem.api.spaces.AsyncSpacesAPI`
        memories: :class:`~goodmem.api.memories.AsyncMemoriesAPI`
        apikeys: :class:`~goodmem.api.apikeys.AsyncApikeysAPI`
        users: :class:`~goodmem.api.users.AsyncUsersAPI`
        ocr: :class:`~goodmem.api.ocr.AsyncOcrAPI`
        system: :class:`~goodmem.api.system.AsyncSystemAPI`
        admin: :class:`~goodmem.api.admin.AsyncAdminAPI`
    """

    def __init__(
        self,
        base_url: str,
        api_key: str,
        *,
        timeout: float = 30.0,
        **kwargs,
    ) -> None:
        self._http = httpx.AsyncClient(base_url=base_url, timeout=timeout, **kwargs)
        self._headers = _auth_headers(api_key)

        self.embedders = AsyncEmbeddersAPI(self._http, self._headers)
        self.rerankers = AsyncRerankersAPI(self._http, self._headers)
        self.llms = AsyncLlmsAPI(self._http, self._headers)
        self.spaces = AsyncSpacesAPI(self._http, self._headers)
        self.memories = AsyncMemoriesAPI(self._http, self._headers)
        self.apikeys = AsyncApikeysAPI(self._http, self._headers)
        self.users = AsyncUsersAPI(self._http, self._headers)
        self.ocr = AsyncOcrAPI(self._http, self._headers)
        self.system = AsyncSystemAPI(self._http, self._headers)
        self.admin = AsyncAdminAPI(self._http, self._headers)

    async def close(self) -> None:
        await self._http.aclose()

    async def __aenter__(self) -> AsyncGoodmem:
        return self

    async def __aexit__(self, *args) -> None:
        await self.close()
