"""
KIESSCLAW LLM Router
Provider-agnostic interface: OpenAI | Anthropic | Ollama | OpenAI-compatible
"""

from __future__ import annotations
import os
import logging
from typing import Optional, Any
from dataclasses import dataclass

logger = logging.getLogger(__name__)


@dataclass
class LLMResponse:
    """Standardized response from any LLM provider."""
    content: str
    model: str
    provider: str
    usage: dict[str, int]
    raw: Any = None


class LLMRouter:
    """
    Routes LLM calls to the configured provider.
    Swap providers by changing LLM_PROVIDER env var or config.yaml.
    """

    def __init__(self, config: dict):
        self.config = config
        self.provider = config.get("provider", "openai")
        self.model = config.get("default_model", "gpt-4o")
        self.api_key = self._resolve_env(config.get("api_key", ""))
        self.base_url = config.get("base_url", "https://api.openai.com/v1")
        self.max_tokens = config.get("max_tokens", 4096)
        self.temperature = config.get("temperature", 0.7)
        self._client = None

    def _resolve_env(self, value: str) -> str:
        """Resolve ${ENV_VAR} references in config values."""
        if isinstance(value, str) and value.startswith("${") and value.endswith("}"):
            env_key = value[2:-1]
            return os.getenv(env_key, "")
        return value

    def _get_client(self):
        if self._client:
            return self._client

        if self.provider in ("openai", "openai-compatible", "ollama"):
            from openai import OpenAI
            kwargs = {"api_key": self.api_key or "ollama"}
            if self.provider != "openai":
                kwargs["base_url"] = self.base_url
            self._client = OpenAI(**kwargs)

        elif self.provider == "anthropic":
            from anthropic import Anthropic
            self._client = Anthropic(api_key=self.api_key)

        else:
            raise ValueError(f"Unsupported provider: {self.provider}")

        return self._client

    def chat(
        self,
        messages: list[dict],
        model: Optional[str] = None,
        system: Optional[str] = None,
        temperature: Optional[float] = None,
        max_tokens: Optional[int] = None,
    ) -> LLMResponse:
        """
        Send a chat completion request to the configured provider.

        Args:
            messages: List of {"role": "user"|"assistant", "content": str}
            model: Override default model
            system: System prompt
            temperature: Override default temperature
            max_tokens: Override default max_tokens

        Returns:
            LLMResponse with .content, .model, .provider, .usage
        """
        model = model or self.model
        temperature = temperature if temperature is not None else self.temperature
        max_tokens = max_tokens or self.max_tokens
        client = self._get_client()

        if self.provider in ("openai", "openai-compatible", "ollama"):
            return self._openai_chat(client, messages, model, system, temperature, max_tokens)
        elif self.provider == "anthropic":
            return self._anthropic_chat(client, messages, model, system, temperature, max_tokens)

    def _openai_chat(self, client, messages, model, system, temperature, max_tokens) -> LLMResponse:
        full_messages = []
        if system:
            full_messages.append({"role": "system", "content": system})
        full_messages.extend(messages)

        response = client.chat.completions.create(
            model=model,
            messages=full_messages,
            temperature=temperature,
            max_tokens=max_tokens,
        )

        return LLMResponse(
            content=response.choices[0].message.content,
            model=response.model,
            provider=self.provider,
            usage={
                "prompt_tokens": response.usage.prompt_tokens,
                "completion_tokens": response.usage.completion_tokens,
                "total_tokens": response.usage.total_tokens,
            },
            raw=response,
        )

    def _anthropic_chat(self, client, messages, model, system, temperature, max_tokens) -> LLMResponse:
        kwargs = {
            "model": model,
            "messages": messages,
            "temperature": temperature,
            "max_tokens": max_tokens,
        }
        if system:
            kwargs["system"] = system

        response = client.messages.create(**kwargs)

        return LLMResponse(
            content=response.content[0].text,
            model=response.model,
            provider="anthropic",
            usage={
                "prompt_tokens": response.usage.input_tokens,
                "completion_tokens": response.usage.output_tokens,
                "total_tokens": response.usage.input_tokens + response.usage.output_tokens,
            },
            raw=response,
        )
