"""
OpenAI-kompatible Chat Completion Models.

Basiert auf OpenAI API Spezifikation:
https://platform.openai.com/docs/api-reference/chat/create
"""

from __future__ import annotations
from typing import Optional, Literal, Any, Union, List, Dict
from pydantic import BaseModel, Field
import time
import uuid


class FunctionCall(BaseModel):
    """Function call in einer Tool-Anfrage."""
    name: str
    arguments: str  # JSON string


class ToolCall(BaseModel):
    """Tool Call vom Modell."""
    id: str = Field(default_factory=lambda: f"call_{uuid.uuid4().hex[:12]}")
    type: Literal["function"] = "function"
    function: FunctionCall


class ChatMessage(BaseModel):
    """Eine Nachricht im Chat."""
    role: Literal["system", "user", "assistant", "tool"]
    content: Optional[str] = None
    name: Optional[str] = None
    tool_call_id: Optional[str] = None
    tool_calls: Optional[list[ToolCall]] = None


class ToolFunction(BaseModel):
    """Definition einer Tool-Funktion."""
    name: str
    description: Optional[str] = None
    parameters: dict[str, Any] = Field(default_factory=dict)


class Tool(BaseModel):
    """Tool-Definition für Function Calling."""
    type: Literal["function"] = "function"
    function: ToolFunction


class RequestMetadata(BaseModel):
    """Zusätzliche Metadaten für die Anfrage."""
    playbook_id: Optional[str] = None
    tenant_id: Optional[str] = None
    user_id: Optional[str] = None


class ChatCompletionRequest(BaseModel):
    """Request für Chat Completions."""
    model: str
    messages: list[ChatMessage]
    stream: bool = False
    temperature: Optional[float] = Field(default=0.7, ge=0, le=2)
    top_p: Optional[float] = Field(default=1.0, ge=0, le=1)
    max_tokens: Optional[int] = Field(default=None, ge=1)
    stop: Optional[Union[List[str], str]] = None
    presence_penalty: Optional[float] = Field(default=0, ge=-2, le=2)
    frequency_penalty: Optional[float] = Field(default=0, ge=-2, le=2)
    user: Optional[str] = None
    tools: Optional[list[Tool]] = None
    tool_choice: Optional[Union[str, Dict[str, Any]]] = None
    metadata: Optional[RequestMetadata] = None


class ChatChoice(BaseModel):
    """Ein Choice in der Response."""
    index: int = 0
    message: ChatMessage
    finish_reason: Optional[Literal["stop", "length", "tool_calls", "content_filter"]] = None


class ChatChoiceDelta(BaseModel):
    """Delta für Streaming Response."""
    role: Optional[str] = None
    content: Optional[str] = None
    tool_calls: Optional[list[ToolCall]] = None


class StreamChoice(BaseModel):
    """Choice in Streaming Response."""
    index: int = 0
    delta: ChatChoiceDelta
    finish_reason: Optional[Literal["stop", "length", "tool_calls", "content_filter"]] = None


class Usage(BaseModel):
    """Token Usage Statistiken."""
    prompt_tokens: int = 0
    completion_tokens: int = 0
    total_tokens: int = 0


class ChatCompletionResponse(BaseModel):
    """Response für Chat Completions (non-streaming)."""
    id: str = Field(default_factory=lambda: f"chatcmpl-{uuid.uuid4().hex[:12]}")
    object: Literal["chat.completion"] = "chat.completion"
    created: int = Field(default_factory=lambda: int(time.time()))
    model: str
    choices: list[ChatChoice]
    usage: Optional[Usage] = None


class ChatCompletionChunk(BaseModel):
    """Chunk für Streaming Response."""
    id: str = Field(default_factory=lambda: f"chatcmpl-{uuid.uuid4().hex[:12]}")
    object: Literal["chat.completion.chunk"] = "chat.completion.chunk"
    created: int = Field(default_factory=lambda: int(time.time()))
    model: str
    choices: list[StreamChoice]


# Model Info
class ModelInfo(BaseModel):
    """Information über ein verfügbares Modell."""
    id: str
    object: Literal["model"] = "model"
    created: int = Field(default_factory=lambda: int(time.time()))
    owned_by: str = "breakpilot"
    description: Optional[str] = None
    context_length: int = 8192


class ModelListResponse(BaseModel):
    """Response für /v1/models."""
    object: Literal["list"] = "list"
    data: list[ModelInfo]
