# aiel_sdk/client.py
from __future__ import annotations

import os
from typing import Any, Dict, Mapping, Optional

from ..services.integrations import IntegrationsService
from ..services.memory import MemoryService
from ..transport import RetryPolicy, Transport, UrllibTransport


def _try_get_keyring_token(service: str = "aiel", username: str = "default") -> str | None:
    try:
        import keyring  # type: ignore
    except Exception:
        return None
    try:
        return keyring.get_password(service, username)
    except Exception:
        return None


def _resolve_token(explicit: str | None) -> str | None:
    if explicit:
        return explicit
    env_token = os.getenv("AIEL_TOKEN")
    if env_token:
        return env_token
    kr = _try_get_keyring_token()
    if kr:
        return kr
    return None


class AielClient:
    """
    Root client (AWS-SDK style):
      - auth, headers, base_url, timeout
      - transport + retry
      - service clients: integrations, memory
    """

    def __init__(
        self,
        *,
        base_url: str,
        api_key: str | None = None,
        timeout: float = 30.0,
        extra_headers: Optional[Dict[str, str]] = None,
        use_x_api_token_fallback: bool = False,
        transport: Optional[Transport] = None,
        retry_policy: Optional[RetryPolicy] = None,
        user_agent: Optional[str] = None,
    ) -> None:
        self.base_url = base_url.rstrip("/")
        if not self.base_url:
            raise ValueError("base_url is required")

        self.timeout = timeout
        self.extra_headers = extra_headers or {}
        self.use_x_api_token_fallback = use_x_api_token_fallback

        self._token = _resolve_token(api_key)

        self.transport = transport or UrllibTransport()
        self.retry_policy = retry_policy or RetryPolicy()
        self.user_agent = user_agent or "aiel-sdk/0.1 (urllib)"

        # Services
        self.integrations = IntegrationsService(self)
        self.memory = MemoryService(self)

    def _build_headers(self) -> Dict[str, str]:
        headers = {
            "Accept": "application/json",
            "User-Agent": self.user_agent,
            **self.extra_headers,
        }
        if self._token:
            headers["Authorization"] = f"Bearer {self._token}"
            if self.use_x_api_token_fallback:
                headers["X-API-Token"] = self._token
        return headers

    def _request(
        self,
        service: str,
        method: str,
        path: str,
        *,
        params: Mapping[str, Any] | None = None,
        json_body: Any | None = None,
        timeout: float | None = None,
        request_id: str | None = None,
    ) -> Any:
        return self.transport.request(
            service=service,
            method=method,
            base_url=self.base_url,
            path=path,
            headers=self._build_headers(),
            params=params,
            json_body=json_body,
            timeout=self.timeout if timeout is None else timeout,
            retry=self.retry_policy,
            request_id=request_id,
        )