"""
Boring-OS SDK model data models.

Pydantic models for direct LLM operations via the Model Gateway,
including completions, streaming chunks, embeddings, and model info.
"""

from __future__ import annotations

from typing import Any

from pydantic import BaseModel, Field


# =============================================================================
# Usage Models
# =============================================================================

class ModelUsage(BaseModel):
    """Token usage for a model completion."""

    input_tokens: int = Field(default=0, description="Input tokens consumed")
    output_tokens: int = Field(default=0, description="Output tokens generated")
    cost: float = Field(default=0.0, description="Estimated cost in USD")


# =============================================================================
# Completion Models
# =============================================================================

class ModelCompletion(BaseModel):
    """
    Response from a model completion call.

    Returned by `boring.models.complete()`.
    """

    text: str = Field(default="", description="Generated text content")
    model: str = Field(default="", description="Model that generated the response")
    provider: str = Field(default="", description="Provider that served the request")
    usage: ModelUsage = Field(
        default_factory=ModelUsage,
        description="Token usage breakdown",
    )
    finish_reason: str = Field(
        default="stop",
        description="Reason generation stopped (stop, length, tool_calls)",
    )
    tool_calls: list[dict[str, Any]] = Field(
        default_factory=list,
        description="Tool calls requested by the model",
    )

    @property
    def cost(self) -> float:
        """Shorthand for usage.cost."""
        return self.usage.cost


class ModelStreamChunk(BaseModel):
    """
    A streaming chunk from a model completion.

    Yielded by `boring.models.stream()`.
    The final chunk has `done=True` and includes usage info.
    """

    text: str = Field(default="", description="Incremental text content")
    done: bool = Field(default=False, description="True on the final chunk")
    model: str = Field(default="", description="Model generating the response")
    usage: ModelUsage | None = Field(
        default=None,
        description="Token usage (only on final chunk)",
    )


# =============================================================================
# Embedding Models
# =============================================================================

class ModelEmbedding(BaseModel):
    """
    Response from an embedding generation call.

    Returned by `boring.models.embed()`.
    """

    embeddings: list[list[float]] = Field(
        description="Embedding vectors, one per input text",
    )
    model: str = Field(default="", description="Embedding model used")
    usage: dict[str, Any] = Field(
        default_factory=dict,
        description="Token usage info (e.g., total_tokens)",
    )


# =============================================================================
# Model Info
# =============================================================================

class ModelInfo(BaseModel):
    """
    Information about an available model.

    Returned by `boring.models.list()`.
    """

    name: str = Field(description="Model name (e.g., claude-sonnet-4)")
    provider: str = Field(description="Provider (anthropic, openai, bedrock)")
    input_price_per_million: float = Field(
        default=0.0,
        description="Cost per million input tokens",
    )
    output_price_per_million: float = Field(
        default=0.0,
        description="Cost per million output tokens",
    )
    max_context_tokens: int = Field(
        default=0,
        description="Maximum context window size in tokens",
    )
