"""OpenAI provider."""

from __future__ import annotations

from typing import Any

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


class OpenAIProvider(BaseProvider):
    """Provider for OpenAI models.

    Requires openai SDK installed:
        pip install ai-qa-sdk[openai]

    Attributes:
        name: Always "openai".
        model: Model name (e.g., "gpt-4-turbo").
        api_key: API key for authentication.
    """

    name = "openai"

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

        Args:
            model: Model name (e.g., "gpt-4").
            api_key: Optional API key (uses OPENAI_API_KEY env var if not set).
            **kwargs: Additional config (max_tokens, temperature, etc.).

        Raises:
            ProviderNotConfiguredError: If openai SDK is not installed.
        """
        super().__init__(model, **kwargs)
        self.api_key = api_key

        try:
            from openai import OpenAI
        except ImportError as e:
            raise ProviderNotConfiguredError(
                "OpenAI provider requires the openai package.\n"
                "Install it with: pip install ai-qa-sdk[openai]"
            ) from e

        self.client = OpenAI(api_key=api_key)

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

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

        Returns:
            Dict with score, evidence, cost_usd, tokens.

        Raises:
            ProviderAPIError: If API call fails.
        """
        try:
            response = self.client.chat.completions.create(
                model=self.model,
                max_tokens=self.config.get("max_tokens", 1024),
                messages=[
                    {"role": "system", "content": system},
                    {"role": "user", "content": user},
                ],
                temperature=self.config.get("temperature", 0.0),
            )

            # Parse response content
            content = response.choices[0].message.content or ""

            # Extract 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

            # Calculate cost (rough estimate)
            # GPT-4: $0.03/1k input, $0.06/1k output
            input_tokens = response.usage.prompt_tokens
            output_tokens = response.usage.completion_tokens
            cost_usd = (input_tokens * 0.03 + output_tokens * 0.06) / 1000

            return {
                "score": score,
                "evidence": evidence if evidence else content[:500],
                "cost_usd": cost_usd,
                "tokens": {
                    "input": input_tokens,
                    "output": output_tokens,
                },
            }
        except Exception as e:
            if "ProviderAPIError" in str(type(e).__mro__):
                raise
            raise ProviderAPIError(
                f"OpenAI API call failed: {type(e).__name__}: {str(e)}"
            ) from e

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

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

        Returns:
            Generated text.

        Raises:
            ProviderAPIError: If API call fails.
        """
        try:
            messages: list[dict[str, str]] = []
            if system:
                messages.append({"role": "system", "content": system})
            messages.append({"role": "user", "content": prompt})

            response = self.client.chat.completions.create(
                model=self.model,
                max_tokens=self.config.get("max_tokens", 1024),
                messages=messages,
                temperature=self.config.get("temperature", 0.7),
            )
            return response.choices[0].message.content or ""
        except Exception as e:
            if "ProviderAPIError" in str(type(e).__mro__):
                raise
            raise ProviderAPIError(
                f"OpenAI API call failed: {type(e).__name__}: {str(e)}"
            ) from e
