"""Top-level Primitif client — one API key, all products."""

from __future__ import annotations

import os

import httpx

from primitif._exceptions import PrimitifError
from primitif._transport import DEFAULT_MAX_RETRIES
from primitif.approval.client import ApprovalAdmin
from primitif.audit.client import AuditAdmin
from primitif.mail.client import MailAdmin
from primitif.namespace.client import NamespaceAdmin

DEFAULT_MAIL_URL = "https://api.mail.primitif.ai"
DEFAULT_APPROVAL_URL = "https://api.approval.primitif.ai"
DEFAULT_AUDIT_URL = "https://api.audit.primitif.ai"
DEFAULT_PLATFORM_URL = "https://api.primitif.ai"


class Primitif:
    """Primitif SDK client — one API key, access to all products.

    Usage::

        with Primitif() as p:  # reads PRIMITIF_API_KEY from env
            mb = p.mail.create_mailbox(name="agent", ttl=3600)
            mb.send(to="user@example.com", subject="Hi", body_text="Hello")
            mb.delete()

            req = p.approval.create_request(action="Send contract")

            ns = p.namespaces.create("staging")
    """

    def __init__(
        self,
        api_key: str | None = None,
        *,
        mail_url: str | None = None,
        approval_url: str | None = None,
        audit_url: str | None = None,
        platform_url: str | None = None,
        max_retries: int = DEFAULT_MAX_RETRIES,
        timeout: float = 30.0,
    ) -> None:
        from primitif._version import __version__

        if api_key is None:
            api_key = os.environ.get("PRIMITIF_API_KEY")
        if api_key is not None:
            api_key = api_key.strip()
        if not api_key:
            raise PrimitifError(
                message="No API key provided. Pass api_key= or set PRIMITIF_API_KEY env var."
            )

        if mail_url is None:
            mail_url = os.environ.get("PRIMITIF_MAIL_URL", DEFAULT_MAIL_URL)
        if approval_url is None:
            approval_url = os.environ.get("PRIMITIF_APPROVAL_URL", DEFAULT_APPROVAL_URL)
        if audit_url is None:
            audit_url = os.environ.get("PRIMITIF_AUDIT_URL", DEFAULT_AUDIT_URL)
        if platform_url is None:
            platform_url = os.environ.get("PRIMITIF_PLATFORM_URL", DEFAULT_PLATFORM_URL)

        headers = {
            "Authorization": f"Bearer {api_key}",
            "User-Agent": f"primitif/{__version__}",
        }

        self._mail_client = httpx.Client(
            base_url=mail_url.rstrip("/"),
            headers=headers,
            timeout=timeout,
        )
        try:
            self._approval_client = httpx.Client(
                base_url=approval_url.rstrip("/"),
                headers=headers,
                timeout=timeout,
            )
        except BaseException:
            self._mail_client.close()
            raise
        try:
            self._audit_client = httpx.Client(
                base_url=audit_url.rstrip("/"),
                headers=headers,
                timeout=timeout,
            )
        except BaseException:
            self._mail_client.close()
            self._approval_client.close()
            raise
        try:
            self._platform_client = httpx.Client(
                base_url=platform_url.rstrip("/"),
                headers=headers,
                timeout=timeout,
            )
        except BaseException:
            self._mail_client.close()
            self._approval_client.close()
            self._audit_client.close()
            raise
        self._max_retries = max_retries

        self.mail = MailAdmin(self._mail_client, max_retries, mail_url.rstrip("/"))
        self.approval = ApprovalAdmin(self._approval_client, max_retries)
        self.audit = AuditAdmin(self._audit_client, max_retries)
        self.namespaces = NamespaceAdmin(self._platform_client, max_retries)

    def close(self) -> None:
        """Close all HTTP clients."""
        self._mail_client.close()
        self._approval_client.close()
        self._audit_client.close()
        self._platform_client.close()

    def __enter__(self) -> Primitif:
        return self

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

    def __repr__(self) -> str:
        return "Primitif()"
