"""Type definitions for models endpoint."""

from typing import Optional

from openai import BaseModel as OpenAIBaseModel
from pydantic import BaseModel, Field


class ModelPricing(OpenAIBaseModel):
    """Model pricing information."""

    prompt: str
    """Cost per token for prompt (as string for precision)."""

    completion: str
    """Cost per token for completion (as string for precision)."""

    image: Optional[str] = None
    """Cost per image."""

    request: Optional[str] = None
    """Cost per request."""

    def prompt_cost_per_million(self) -> float:
        """Get prompt cost per 1M tokens."""
        return float(self.prompt) * 1_000_000

    def completion_cost_per_million(self) -> float:
        """Get completion cost per 1M tokens."""
        return float(self.completion) * 1_000_000


class ModelArchitecture(OpenAIBaseModel):
    """Model architecture details."""

    tokenizer: Optional[str] = None
    """Tokenizer type (e.g., "GPT", "Claude")."""

    instruct_type: Optional[str] = None
    """Instruction format type."""

    modality: Optional[str] = None
    """Model modality (e.g., "text", "text+image")."""


class TopProvider(OpenAIBaseModel):
    """Top provider information."""

    context_length: Optional[int] = None
    """Maximum context length for top provider."""

    max_completion_tokens: Optional[int] = None
    """Maximum completion tokens."""

    is_moderated: bool = False
    """Whether content is moderated."""


class Model(OpenAIBaseModel):
    """OpenRouter model information."""

    id: str
    """Model ID (e.g., 'openai/gpt-4o', 'anthropic/claude-3.5-sonnet')."""

    name: str
    """Display name."""

    description: Optional[str] = None
    """Model description."""

    context_length: int = 4096
    """Maximum context length in tokens."""

    pricing: ModelPricing
    """Pricing information."""

    architecture: Optional[ModelArchitecture] = None
    """Architecture details."""

    top_provider: Optional[TopProvider] = None
    """Top provider information."""

    per_request_limits: Optional[dict] = None
    """Per-request rate limits."""

    created: Optional[int] = None
    """Unix timestamp of model creation."""

    @property
    def owned_by(self) -> str:
        """Extract owner from model ID."""
        if "/" in self.id:
            return self.id.split("/")[0]
        return "unknown"

    @property
    def supports_vision(self) -> bool:
        """Check if model supports vision/images."""
        if self.architecture and self.architecture.modality:
            return "image" in self.architecture.modality.lower()
        return False


class ModelsResponse(OpenAIBaseModel):
    """Response from models list endpoint."""

    object: str = "list"
    """Object type, always 'list'."""

    data: list[Model]
    """List of available models."""


class ModelsFilter(BaseModel):
    """Filter options for models list."""

    provider: Optional[str] = Field(default=None, description="Filter by provider (e.g., 'openai', 'anthropic')")
    """Filter by provider name."""

    supports_vision: Optional[bool] = Field(default=None, description="Filter for vision-capable models")
    """Filter for models with vision support."""

    supports_tools: Optional[bool] = Field(default=None, description="Filter for tool-use capable models")
    """Filter for models with tool/function calling support."""

    min_context_length: Optional[int] = Field(default=None, ge=1, description="Minimum context length")
    """Filter by minimum context length."""

    max_prompt_price: Optional[float] = Field(default=None, ge=0, description="Maximum prompt price per 1M tokens")
    """Filter by maximum prompt price per 1M tokens."""

    max_completion_price: Optional[float] = Field(default=None, ge=0, description="Maximum completion price per 1M tokens")
    """Filter by maximum completion price per 1M tokens."""

    search: Optional[str] = Field(default=None, min_length=1, description="Search in model ID and name")
    """Search string to match in model ID or name."""
