"""
OpenAI-compatible client for SpendLil proxy.
Mirrors the `openai` package's interface so it can be used as a drop-in replacement.
"""
from __future__ import annotations

from typing import Any, AsyncGenerator, Dict, List, Optional

from .client import (
    SpendLilConfig,
    SpendLilError,
    SpendLilMeta,
    async_proxy_request,
    async_stream_sse,
    proxy_request,
)


class _ChatCompletions:
    """Mirrors openai.chat.completions interface."""

    def __init__(self, cfg: SpendLilConfig, api_key: str):
        self._cfg = cfg
        self._api_key = api_key
        self._auth = {"Authorization": f"Bearer {api_key}"}

    # ── Sync ──────────────────────────────────────────────

    def create(
        self,
        *,
        model: str,
        messages: List[Dict[str, str]],
        temperature: Optional[float] = None,
        max_tokens: Optional[int] = None,
        session_key: Optional[str] = None,
        priority: Optional[str] = None,
        **kwargs: Any,
    ) -> Dict[str, Any]:
        """
        Synchronous chat completion. Returns a dict that mirrors the OpenAI
        response shape, with an extra ``_spendlil`` key containing proxy metadata.
        """
        body: Dict[str, Any] = {"model": model, "messages": messages, **kwargs}
        if temperature is not None:
            body["temperature"] = temperature
        if max_tokens is not None:
            body["max_tokens"] = max_tokens

        status, headers, resp_body = proxy_request(
            self._cfg,
            "/proxy/openai/v1/chat/completions",
            body,
            self._auth,
            session_key or self._cfg.session_key,
            priority,
        )

        if status >= 400:
            meta = SpendLilMeta.from_headers(headers)
            msg = resp_body.get("error", {})
            msg = msg.get("message", str(msg)) if isinstance(msg, dict) else str(msg)
            raise SpendLilError(status, msg, resp_body, meta)

        resp_body["_spendlil"] = SpendLilMeta.from_headers(headers)
        return resp_body

    def auto_create(
        self,
        *,
        messages: List[Dict[str, str]],
        model: Optional[str] = None,
        session_key: Optional[str] = None,
        priority: Optional[str] = None,
        **kwargs: Any,
    ) -> Dict[str, Any]:
        """
        Auto-routed completion — SpendLil selects the best model.
        Provide multiple provider keys via extra_headers if you have them.
        """
        body: Dict[str, Any] = {"messages": messages, **kwargs}
        if model:
            body["model"] = model

        status, headers, resp_body = proxy_request(
            self._cfg,
            "/proxy/auto/v1/chat/completions",
            body,
            {"x-openai-key": self._api_key},
            session_key or self._cfg.session_key,
            priority,
        )

        if status >= 400:
            meta = SpendLilMeta.from_headers(headers)
            msg = resp_body.get("error", {})
            msg = msg.get("message", str(msg)) if isinstance(msg, dict) else str(msg)
            raise SpendLilError(status, msg, resp_body, meta)

        resp_body["_spendlil"] = SpendLilMeta.from_headers(headers)
        return resp_body

    # ── Async ─────────────────────────────────────────────

    async def async_create(
        self,
        *,
        model: str,
        messages: List[Dict[str, str]],
        temperature: Optional[float] = None,
        max_tokens: Optional[int] = None,
        session_key: Optional[str] = None,
        priority: Optional[str] = None,
        **kwargs: Any,
    ) -> Dict[str, Any]:
        """Async chat completion."""
        body: Dict[str, Any] = {"model": model, "messages": messages, **kwargs}
        if temperature is not None:
            body["temperature"] = temperature
        if max_tokens is not None:
            body["max_tokens"] = max_tokens

        status, headers, resp_body = await async_proxy_request(
            self._cfg,
            "/proxy/openai/v1/chat/completions",
            body,
            self._auth,
            session_key or self._cfg.session_key,
            priority,
        )

        if status >= 400:
            meta = SpendLilMeta.from_headers(headers)
            msg = resp_body.get("error", {})
            msg = msg.get("message", str(msg)) if isinstance(msg, dict) else str(msg)
            raise SpendLilError(status, msg, resp_body, meta)

        resp_body["_spendlil"] = SpendLilMeta.from_headers(headers)
        return resp_body

    async def async_stream(
        self,
        *,
        model: str,
        messages: List[Dict[str, str]],
        temperature: Optional[float] = None,
        max_tokens: Optional[int] = None,
        session_key: Optional[str] = None,
        **kwargs: Any,
    ) -> AsyncGenerator[Dict[str, Any], None]:
        """Async streaming chat completion. Yields SSE delta objects."""
        body: Dict[str, Any] = {
            "model": model,
            "messages": messages,
            "stream": True,
            "stream_options": {"include_usage": True},
            **kwargs,
        }
        if temperature is not None:
            body["temperature"] = temperature
        if max_tokens is not None:
            body["max_tokens"] = max_tokens

        async for chunk in async_stream_sse(
            self._cfg,
            "/proxy/openai/v1/chat/completions",
            body,
            self._auth,
            session_key or self._cfg.session_key,
        ):
            yield chunk


class _Chat:
    def __init__(self, cfg: SpendLilConfig, api_key: str):
        self.completions = _ChatCompletions(cfg, api_key)


class SpendLilOpenAI:
    """
    OpenAI-compatible client routed through SpendLil.

    Usage::

        sl = SpendLil(agent_id="xxx", base_url="https://spendlil.yourco.com/api")
        openai = sl.openai(api_key=os.environ["OPENAI_API_KEY"])

        response = openai.chat.completions.create(
            model="gpt-4o",
            messages=[{"role": "user", "content": "Hello!"}],
        )
        print(response["choices"][0]["message"]["content"])
        print(response["_spendlil"].tier)  # 'frontier'
    """

    def __init__(self, cfg: SpendLilConfig, api_key: str):
        self._cfg = cfg
        self._api_key = api_key
        self.chat = _Chat(cfg, api_key)
