"""Pydantic models for OpenAI-compatible API."""

import time
import uuid
from typing import Literal

from pydantic import BaseModel, Field, field_validator


class Message(BaseModel):
    """Chat message."""

    role: Literal["system", "user", "assistant", "tool"]
    content: str

    @field_validator("content")
    @classmethod
    def content_size_limit(cls, v: str) -> str:
        if len(v) > 102_400:
            raise ValueError(f"content exceeds 100KB limit ({len(v)} chars)")
        return v


class ChatCompletionRequest(BaseModel):
    """Request body for chat completions."""

    model: str
    messages: list[Message]
    temperature: float = 1.0
    max_tokens: int | None = None
    stream: bool = False

    @field_validator("messages")
    @classmethod
    def messages_not_empty(cls, v: list[Message]) -> list[Message]:
        if not v:
            raise ValueError("messages must contain at least one message")
        return v

    @field_validator("temperature")
    @classmethod
    def temperature_in_range(cls, v: float) -> float:
        if not 0.0 <= v <= 2.0:
            raise ValueError(f"temperature must be between 0.0 and 2.0, got {v}")
        return v

    @field_validator("max_tokens")
    @classmethod
    def max_tokens_positive(cls, v: int | None) -> int | None:
        if v is not None and v <= 0:
            raise ValueError(f"max_tokens must be positive, got {v}")
        return v

    @field_validator("model")
    @classmethod
    def model_not_empty(cls, v: str) -> str:
        if not v.strip():
            raise ValueError("model must not be empty")
        return v


class Choice(BaseModel):
    """A completion choice."""

    index: int = 0
    message: Message
    finish_reason: str = "stop"


class Usage(BaseModel):
    """Token usage statistics."""

    prompt_tokens: int
    completion_tokens: int
    total_tokens: int


class RoutingInfo(BaseModel):
    """Routing decision metadata from Robot Resources."""

    selected_model: str
    original_model: str
    provider: str
    task_type: str
    capability_score: float
    savings_percent: float
    baseline_model: str
    reasoning: str


class ChatCompletionResponse(BaseModel):
    """Response body for chat completions."""

    id: str = Field(default_factory=lambda: f"chatcmpl-{uuid.uuid4().hex[:12]}")
    object: str = "chat.completion"
    created: int = Field(default_factory=lambda: int(time.time()))
    model: str
    choices: list[Choice]
    usage: Usage
    routing_info: RoutingInfo | None = None


class StreamDelta(BaseModel):
    """Delta content for streaming."""

    role: str | None = None
    content: str | None = None


class StreamChoice(BaseModel):
    """A streaming choice."""

    index: int = 0
    delta: StreamDelta
    finish_reason: str | None = None


class ChatCompletionChunk(BaseModel):
    """A streaming chunk."""

    id: str
    object: str = "chat.completion.chunk"
    created: int
    model: str
    choices: list[StreamChoice]
