"""Local provider for Ollama/vLLM."""

from __future__ import annotations

from typing import Any

from ai_qa.exceptions import ProviderAPIError, ProviderNotConfiguredError
from ai_qa.providers.base import BaseProvider


class LocalProvider(BaseProvider):
    """Provider for local LLM services (Ollama, vLLM, etc.).

    Requires httpx for HTTP calls (included in core).

    Attributes:
        name: Always "local".
        model: Model name (e.g., "llama2").
        base_url: API endpoint (default: http://localhost:11434).
    """

    name = "local"

    def __init__(
        self,
        model: str,
        base_url: str | None = None,
        **kwargs: Any,
    ) -> None:
        """Initialize local provider.

        Args:
            model: Model name (e.g., "llama2", "mistral").
            base_url: API endpoint (default: http://localhost:11434).
            **kwargs: Additional config.

        Raises:
            ProviderNotConfiguredError: If httpx is not available.
        """
        super().__init__(model, **kwargs)
        self.base_url = base_url or "http://localhost:11434"

        try:
            import httpx
        except ImportError as e:
            raise ProviderNotConfiguredError(
                "Local provider requires httpx.\n"
                "Install it with: pip install httpx"
            ) from e

        self.client = httpx.Client(base_url=self.base_url)

    def judge(
        self,
        system: str,
        user: str,
    ) -> dict[str, Any]:
        """Call local model to judge output.

        Args:
            system: System prompt.
            user: User prompt.

        Returns:
            Dict with score, evidence, cost_usd (0), tokens.

        Raises:
            ProviderAPIError: If API call fails.
        """
        try:
            prompt = f"{system}\n\n{user}"
            response = self.client.post(
                "/api/generate",
                json={
                    "model": self.model,
                    "prompt": prompt,
                    "stream": False,
                },
            )
            response.raise_for_status()

            data = response.json()
            content = data.get("response", "")

            # Parse response for score and evidence
            lines = content.split("\n")
            score = 0.5
            evidence = content

            for line in lines:
                if line.startswith("score:"):
                    try:
                        score = float(line.split(":", 1)[1].strip())
                        score = min(1.0, max(0.0, score))
                    except (ValueError, IndexError):
                        pass
                elif line.startswith("evidence:"):
                    evidence = line.split(":", 1)[1].strip()
                    break

            return {
                "score": score,
                "evidence": evidence if evidence else content[:500],
                "cost_usd": 0.0,  # Local models are free
                "tokens": {},  # Local models don't track tokens
            }
        except Exception as e:
            if "ProviderAPIError" in str(type(e).__mro__):
                raise
            raise ProviderAPIError(
                f"Local provider call failed: {type(e).__name__}: {str(e)}"
            ) from e

    def generate(
        self,
        prompt: str,
        system: str | None = None,
    ) -> str:
        """Generate text using local model.

        Args:
            prompt: Input prompt.
            system: Optional system prompt.

        Returns:
            Generated text.

        Raises:
            ProviderAPIError: If API call fails.
        """
        try:
            full_prompt = prompt
            if system:
                full_prompt = f"{system}\n\n{prompt}"

            response = self.client.post(
                "/api/generate",
                json={
                    "model": self.model,
                    "prompt": full_prompt,
                    "stream": False,
                },
            )
            response.raise_for_status()

            data = response.json()
            return str(data.get("response", ""))
        except Exception as e:
            if "ProviderAPIError" in str(type(e).__mro__):
                raise
            raise ProviderAPIError(
                f"Local provider call failed: {type(e).__name__}: {str(e)}"
            ) from e
