"""
Core OomLlama class - the main interface.
"""

from typing import Optional, List, Dict, Any

from .client import OllamaClient
from .router import ModelRouter, ModelConfig, ModelCapability


class OomLlama:
    """
    Smart LLM interface with routing and TIBET provenance.

    Example:
        llm = OomLlama()
        response = llm.generate("Hello!")

        # Auto-routing
        llm = OomLlama(auto_route=True)
        response = llm.generate("Write Python code")  # Routes to code model

        # With TIBET
        from tibet_core import Provider
        tibet = Provider(actor="my_app")
        llm = OomLlama(tibet=tibet)
    """

    def __init__(
        self,
        model: str = "qwen2.5:7b",
        ollama_url: str = "http://localhost:11434",
        auto_route: bool = False,
        router: Optional[ModelRouter] = None,
        tibet: Optional["Provider"] = None,
        system_prompt: Optional[str] = None
    ):
        """
        Initialize OomLlama.

        Args:
            model: Default model name
            ollama_url: Ollama API URL
            auto_route: Automatically select best model per query
            router: Custom model router
            tibet: TIBETProvider for provenance tracking
            system_prompt: Default system prompt
        """
        self.default_model = model
        self.client = OllamaClient(base_url=ollama_url)
        self.auto_route = auto_route
        self.router = router or ModelRouter()
        self.tibet = tibet
        self.system_prompt = system_prompt

        # Generation defaults
        self.temperature = 0.7
        self.top_p = 0.9
        self.max_tokens = 512

    def generate(
        self,
        prompt: str,
        model: Optional[str] = None,
        system: Optional[str] = None,
        temperature: Optional[float] = None,
        max_tokens: Optional[int] = None,
        prefer_fast: bool = False
    ) -> str:
        """
        Generate text.

        Args:
            prompt: User prompt
            model: Override model (or auto-route if None and auto_route=True)
            system: System prompt override
            temperature: Sampling temperature
            max_tokens: Max tokens to generate
            prefer_fast: Prefer faster model when routing

        Returns:
            Generated text
        """
        # Model selection
        if model:
            selected_model = model
            route_reason = "explicit selection"
        elif self.auto_route:
            config, route_reason = self.router.route_with_reason(prompt, prefer_fast=prefer_fast)
            selected_model = config.name
        else:
            selected_model = self.default_model
            route_reason = "default model"

        # TIBET: Track query
        tibet_token = None
        if self.tibet:
            tibet_token = self.tibet.create(
                action="llm_generate",
                erin={
                    "prompt_preview": prompt[:200],
                    "prompt_length": len(prompt),
                    "model": selected_model
                },
                eromheen={
                    "temperature": temperature or self.temperature,
                    "max_tokens": max_tokens or self.max_tokens,
                    "auto_route": self.auto_route
                },
                erachter=f"LLM generation: {route_reason}"
            )

        # Generate
        try:
            response = self.client.generate(
                model=selected_model,
                prompt=prompt,
                system=system or self.system_prompt,
                temperature=temperature or self.temperature,
                top_p=self.top_p,
                max_tokens=max_tokens or self.max_tokens
            )
            result = response.get("response", "")

            # TIBET: Track response
            if self.tibet and tibet_token:
                self.tibet.create(
                    action="llm_response",
                    erin={
                        "response_preview": result[:200],
                        "response_length": len(result),
                        "model": selected_model,
                        "eval_count": response.get("eval_count"),
                        "eval_duration": response.get("eval_duration")
                    },
                    eraan=[tibet_token.token_id],
                    erachter="LLM response received",
                    parent_id=tibet_token.token_id
                )

            return result

        except Exception as e:
            # TIBET: Track error
            if self.tibet and tibet_token:
                self.tibet.create(
                    action="llm_error",
                    erin={"error": str(e), "model": selected_model},
                    eraan=[tibet_token.token_id],
                    erachter="LLM generation failed",
                    parent_id=tibet_token.token_id
                )
            raise

    def chat(
        self,
        messages: List[Dict[str, str]],
        model: Optional[str] = None,
        temperature: Optional[float] = None,
        max_tokens: Optional[int] = None
    ) -> str:
        """
        Chat-style generation.

        Args:
            messages: List of {"role": "user/assistant", "content": "..."}
            model: Override model
            temperature: Sampling temperature
            max_tokens: Max tokens

        Returns:
            Assistant response
        """
        selected_model = model or self.default_model

        # TIBET: Track chat
        if self.tibet:
            self.tibet.create(
                action="llm_chat",
                erin={
                    "message_count": len(messages),
                    "model": selected_model
                },
                erachter="Chat generation"
            )

        response = self.client.chat(
            model=selected_model,
            messages=messages,
            temperature=temperature or self.temperature,
            max_tokens=max_tokens or self.max_tokens
        )

        return response.get("message", {}).get("content", "")

    def set_defaults(
        self,
        temperature: Optional[float] = None,
        top_p: Optional[float] = None,
        max_tokens: Optional[int] = None,
        system_prompt: Optional[str] = None
    ):
        """Set default generation parameters."""
        if temperature is not None:
            self.temperature = temperature
        if top_p is not None:
            self.top_p = top_p
        if max_tokens is not None:
            self.max_tokens = max_tokens
        if system_prompt is not None:
            self.system_prompt = system_prompt

    def list_models(self) -> List[str]:
        """List available Ollama models."""
        return self.client.list_models()

    def is_available(self) -> bool:
        """Check if Ollama is reachable."""
        return self.client.is_available()

    def __repr__(self) -> str:
        return f"OomLlama(model='{self.default_model}', auto_route={self.auto_route})"
