"""Pydantic response models for ODS Dashboard API."""

from typing import Annotated, Any, Optional

from pydantic import BaseModel, Field

from config import GPU_BACKEND


class GPUInfo(BaseModel):
    name: str
    memory_used_mb: int
    memory_total_mb: int
    memory_percent: float
    utilization_percent: int
    temperature_c: int
    power_w: Optional[float] = None
    memory_type: str = "discrete"
    gpu_backend: str = GPU_BACKEND


class ServiceStatus(BaseModel):
    id: str
    name: str
    port: int
    external_port: int
    status: str  # "healthy", "unhealthy", "unknown", "down", "not_deployed"
    response_time_ms: Optional[float] = None


class DiskUsage(BaseModel):
    path: str
    used_gb: float
    total_gb: float
    percent: float


class ModelInfo(BaseModel):
    name: str
    size_gb: float
    context_length: int
    quantization: Optional[str] = None


class BootstrapStatus(BaseModel):
    active: bool
    model_name: Optional[str] = None
    percent: Optional[float] = None
    downloaded_gb: Optional[float] = None
    total_gb: Optional[float] = None
    speed_mbps: Optional[float] = None
    eta_seconds: Optional[int] = None


class FullStatus(BaseModel):
    timestamp: str
    gpu: Optional[GPUInfo] = None
    services: list[ServiceStatus]
    disk: DiskUsage
    model: Optional[ModelInfo] = None
    bootstrap: BootstrapStatus
    uptime_seconds: int


PortNumber = Annotated[int, Field(ge=1, le=65535)]


class PortCheckRequest(BaseModel):
    ports: list[PortNumber]


class PortConflict(BaseModel):
    port: int
    service: str
    in_use: bool


class PersonaRequest(BaseModel):
    persona: str


class ChatRequest(BaseModel):
    message: str = Field(..., max_length=100000)
    system: Optional[str] = Field(None, max_length=10000)


class VersionInfo(BaseModel):
    current: str
    latest: Optional[str] = None
    update_available: bool = False
    changelog_url: Optional[str] = None
    checked_at: Optional[str] = None


class UpdateAction(BaseModel):
    action: str  # "check", "backup", "update"


class PrivacyShieldStatus(BaseModel):
    enabled: bool
    container_running: bool
    port: int
    target_api: str
    pii_cache_enabled: bool
    message: str


class PrivacyShieldToggle(BaseModel):
    enable: bool


class IndividualGPU(BaseModel):
    index: int
    uuid: str
    name: str
    memory_used_mb: int
    memory_total_mb: int
    memory_percent: float
    utilization_percent: int
    temperature_c: int
    power_w: Optional[float] = None
    assigned_services: list[str] = []


class MultiGPUStatus(BaseModel):
    gpu_count: int
    backend: str  # "nvidia", "amd", "apple"
    gpus: list[IndividualGPU]
    topology: Optional[dict] = None
    assignment: Optional[dict] = None
    split_mode: Optional[str] = None
    tensor_split: Optional[str] = None
    aggregate: GPUInfo


class AmdRuntimeStatus(BaseModel):
    available: bool
    reason: Optional[str] = None
    runtime: str = "none"
    location: str = "none"
    runtimeMode: str = "unknown"
    managedByODS: bool = False
    selectedBackend: str = "none"
    supportedBackends: list[str] = Field(default_factory=list)
    defaultBackend: str = "none"
    apiBase: Optional[str] = None
    healthUrl: Optional[str] = None
    health: Optional[str] = None
    version: str = "unknown"
    loadedModel: Optional[str] = None
    modelCount: Optional[int] = None
    capabilities: list[str] = Field(default_factory=list)
    warnings: list[str] = Field(default_factory=list)


class ModelLibraryEntry(BaseModel):
    id: str
    name: str
    gguf: Optional[str] = None
    ggufParts: Optional[list[dict[str, Any]]] = None
    downloadUrl: Optional[str] = None
    downloadSha256: Optional[str] = None
    llmModelName: Optional[str] = None
    size: str
    sizeGb: float
    vramRequired: float
    estimatedRequired: Optional[float] = None
    contextLength: int
    specialty: str
    description: str
    tokensPerSec: Optional[float] = None
    tokensPerSecEstimate: Optional[float] = None
    quantization: Optional[str] = None
    architecture: Optional[str] = None
    activeParamsB: Optional[float] = None
    metadata: dict[str, Any] = Field(default_factory=dict)
    status: str  # "loaded", "downloaded", "available"
    recommended: bool = False
    configured: bool = False
    recommendation: Optional[dict[str, Any]] = None
    fitsVram: bool
    fitsCurrentVram: bool
    performance: Optional[dict[str, Any]] = None
    performanceLabel: Optional[str] = None


class ModelLibraryGpu(BaseModel):
    vramTotal: float
    vramUsed: float
    vramFree: float


class ModelLibraryResponse(BaseModel):
    models: list[ModelLibraryEntry]
    gpu: Optional[ModelLibraryGpu] = None
    currentModel: Optional[str] = None
    loadedModel: Optional[str] = None
    configuredModel: Optional[str] = None
    recommendationPolicy: Optional[str] = None
    recommendationAlternatives: list[dict[str, Any]] = Field(default_factory=list)
