from __future__ import annotations

from typing import Any, Literal

from pydantic import BaseModel, ConfigDict, Field


class OpenAICompatBaseModel(BaseModel):
    model_config = ConfigDict(extra="allow")


class OpenAIErrorDetail(OpenAICompatBaseModel):
    message: str
    type: str
    param: str | None = None
    code: str | None = None


class OpenAIErrorResponse(OpenAICompatBaseModel):
    error: OpenAIErrorDetail


class ChatCompletionToolFunction(OpenAICompatBaseModel):
    name: str
    description: str | None = None
    parameters: dict[str, Any] | None = None


class ChatCompletionTool(OpenAICompatBaseModel):
    type: Literal["function"] = "function"
    function: ChatCompletionToolFunction


class ChatCompletionToolChoiceFunction(OpenAICompatBaseModel):
    name: str


class ChatCompletionToolChoice(OpenAICompatBaseModel):
    type: Literal["function"] = "function"
    function: ChatCompletionToolChoiceFunction


class ChatCompletionRequestToolCallFunction(OpenAICompatBaseModel):
    name: str
    arguments: str


class ChatCompletionRequestToolCall(OpenAICompatBaseModel):
    id: str | None = None
    type: Literal["function"] = "function"
    function: ChatCompletionRequestToolCallFunction


class ChatCompletionMessage(OpenAICompatBaseModel):
    role: Literal["system", "developer", "user", "assistant", "tool"]
    content: str | list[dict[str, Any]] | None = None
    name: str | None = None
    tool_call_id: str | None = None
    tool_calls: list[ChatCompletionRequestToolCall] | None = None
    refusal: str | None = None


class ChatCompletionRequest(OpenAICompatBaseModel):
    model: str | None = None
    messages: list[ChatCompletionMessage]
    temperature: float | None = None
    top_p: float | None = None
    n: int = Field(default=1, ge=1, le=16)
    stream: bool = False
    stream_options: dict[str, Any] | None = None
    stop: str | list[str] | None = None
    max_tokens: int | None = Field(default=None, ge=1)
    max_completion_tokens: int | None = Field(default=None, ge=1)
    presence_penalty: float | None = None
    frequency_penalty: float | None = None
    tools: list[ChatCompletionTool] | None = None
    tool_choice: str | ChatCompletionToolChoice | None = None
    parallel_tool_calls: bool | None = None
    response_format: dict[str, Any] | None = None
    seed: int | None = None
    user: str | None = None


class ChatCompletionResponseToolCallFunction(OpenAICompatBaseModel):
    name: str
    arguments: str


class ChatCompletionResponseToolCall(OpenAICompatBaseModel):
    id: str
    type: Literal["function"] = "function"
    function: ChatCompletionResponseToolCallFunction


class ChatCompletionResponseMessage(OpenAICompatBaseModel):
    role: Literal["assistant"] = "assistant"
    content: str | list[dict[str, Any]] | None = None
    tool_calls: list[ChatCompletionResponseToolCall] | None = None
    refusal: str | None = None


class ChatCompletionChoice(OpenAICompatBaseModel):
    index: int
    message: ChatCompletionResponseMessage
    finish_reason: str | None = None
    logprobs: dict[str, Any] | None = None


class ChatCompletionUsage(OpenAICompatBaseModel):
    prompt_tokens: int | None = None
    completion_tokens: int | None = None
    total_tokens: int | None = None


class ChatCompletionResponse(OpenAICompatBaseModel):
    id: str
    object: Literal["chat.completion"] = "chat.completion"
    created: int
    model: str
    choices: list[ChatCompletionChoice]
    usage: ChatCompletionUsage | None = None
    system_fingerprint: str | None = None


class ChatCompletionChunkDeltaToolCallFunction(OpenAICompatBaseModel):
    name: str | None = None
    arguments: str | None = None


class ChatCompletionChunkDeltaToolCall(OpenAICompatBaseModel):
    index: int | None = None
    id: str | None = None
    type: Literal["function"] = "function"
    function: ChatCompletionChunkDeltaToolCallFunction | None = None


class ChatCompletionChunkDelta(OpenAICompatBaseModel):
    role: str | None = None
    content: str | list[dict[str, Any]] | None = None
    tool_calls: list[ChatCompletionChunkDeltaToolCall] | None = None
    refusal: str | None = None


class ChatCompletionChunkChoice(OpenAICompatBaseModel):
    index: int
    delta: ChatCompletionChunkDelta
    finish_reason: str | None = None
    logprobs: dict[str, Any] | None = None


class ChatCompletionChunkResponse(OpenAICompatBaseModel):
    id: str
    object: Literal["chat.completion.chunk"] = "chat.completion.chunk"
    created: int
    model: str
    choices: list[ChatCompletionChunkChoice]
    usage: ChatCompletionUsage | None = None
    system_fingerprint: str | None = None


class ModelCard(OpenAICompatBaseModel):
    id: str
    object: Literal["model"] = "model"
    created: int
    owned_by: str


class ModelListResponse(OpenAICompatBaseModel):
    object: Literal["list"] = "list"
    data: list[ModelCard]
