"""Pydantic v2 request/response schemas for the Ilum API."""

from __future__ import annotations

from typing import Any

from pydantic import BaseModel, Field

# ---------------------------------------------------------------------------
# Health
# ---------------------------------------------------------------------------


class HealthResponse(BaseModel):
    """Response for the /health endpoint."""

    status: str = "ok"
    release: str = ""
    namespace: str = ""


# ---------------------------------------------------------------------------
# Errors
# ---------------------------------------------------------------------------


class ErrorResponse(BaseModel):
    """Standard error response body."""

    detail: str
    error_code: str = ""
    suggestion: str = ""


# ---------------------------------------------------------------------------
# Modules
# ---------------------------------------------------------------------------


class ModuleSummary(BaseModel):
    """Compact module info returned in list responses."""

    name: str
    description: str
    category: str
    enabled: bool = False
    default_enabled: bool = False
    required: bool = False
    status: str = "disabled"
    console_path: str = ""
    version: str = ""
    chart_version: str = ""


class PodInfo(BaseModel):
    """Pod status within a module detail response."""

    name: str
    phase: str
    ready: bool
    restart_count: int = 0


class ModuleDetail(BaseModel):
    """Full module info with live pod health."""

    name: str
    description: str
    category: str
    enabled: bool = False
    default_enabled: bool = False
    required: bool = False
    status: str = "disabled"
    console_path: str = ""
    version: str = ""
    chart_version: str = ""
    requires: list[str] = Field(default_factory=list)
    conflicts_with: list[str] = Field(default_factory=list)
    chart_condition: str = ""
    values_key: str = ""
    pods: list[PodInfo] = Field(default_factory=list)


class EnableModuleRequest(BaseModel):
    """Optional request body for POST /modules/{name}/enable."""

    set_flags: list[str] = Field(default_factory=list)


class ModuleValuesResponse(BaseModel):
    """Response for GET /modules/{name}/values."""

    values_key: str
    values: dict[str, Any] = Field(default_factory=dict)


class ConfigFieldResponse(BaseModel):
    """Single config field in a module's schema."""

    path: str
    label: str
    field_type: str
    description: str
    tab: str = "advanced"
    default: Any = None
    current_value: Any = None
    min_value: float | None = None
    max_value: float | None = None
    options: list[str] = Field(default_factory=list)


class ConfigTabResponse(BaseModel):
    """A tab grouping related config fields."""

    name: str
    label: str
    fields: list[ConfigFieldResponse] = Field(default_factory=list)


class ConfigSchemaResponse(BaseModel):
    """Config schema for a module."""

    module_name: str
    values_key: str = ""
    tabs: list[ConfigTabResponse] = Field(default_factory=list)


class ModuleConfigUpdateRequest(BaseModel):
    """Request body for PUT /modules/{name}/config."""

    values: dict[str, Any]


class ModuleLogsResponse(BaseModel):
    """Pod log lines for a module."""

    module_name: str
    pod_name: str
    lines: list[str] = Field(default_factory=list)


# ---------------------------------------------------------------------------
# Release / Status
# ---------------------------------------------------------------------------


class ReleaseResponse(BaseModel):
    """Release info response."""

    name: str
    namespace: str
    status: str
    chart: str
    chart_version: str
    revision: int
    last_deployed: str


class PodStatusResponse(BaseModel):
    """Pod status returned in the pods list."""

    name: str
    namespace: str
    phase: str
    ready: bool
    restart_count: int = 0
    containers: list[str] = Field(default_factory=list)


# ---------------------------------------------------------------------------
# Values
# ---------------------------------------------------------------------------


class ValuesDiffEntry(BaseModel):
    """Single changed key in a values diff."""

    key: str
    old: Any = None
    new: Any = None
    change_type: str  # "added" | "removed" | "changed"


class ValuesDiffResponse(BaseModel):
    """Response for /values/diff."""

    has_drift: bool
    snapshot_exists: bool
    changes: list[ValuesDiffEntry] = Field(default_factory=list)


class ValuesUpdateRequest(BaseModel):
    """Request body for PUT /values."""

    set_flags: list[str] = Field(default_factory=list)


# ---------------------------------------------------------------------------
# Operations
# ---------------------------------------------------------------------------


class OperationLog(BaseModel):
    """Single log entry within an operation."""

    timestamp: str
    message: str
    level: str = "info"


class OperationResponse(BaseModel):
    """Status of an async operation."""

    id: str
    # pending | running | awaiting_readiness | completed | failed | cancelling | cancelled
    status: str
    operation: str  # "enable" | "disable" | "upgrade"
    modules: list[str] = Field(default_factory=list)
    progress: int = 0
    logs: list[OperationLog] = Field(default_factory=list)
    created_at: str = ""
    completed_at: str = ""
    error: str = ""
    error_code: str = ""
    job_name: str = ""  # Non-empty when operation runs via K8s Job
    helm_completed_at: str = ""  # ISO timestamp when the helm Job finished
    expected_revision: int = 0  # Helm revision at time of Job completion


class OperationCreated(BaseModel):
    """Response for 202 Accepted (operation started)."""

    id: str
    status: str = "pending"
    message: str = ""
    warnings: list[str] = []
    auto_resolved: list[str] = []


class OperationCancelResponse(BaseModel):
    """Response for POST /operations/{id}/cancel."""

    id: str
    status: str
    message: str = ""


# ---------------------------------------------------------------------------
# Release recovery
# ---------------------------------------------------------------------------


class ReleaseRecoveryResponse(BaseModel):
    """Response for POST /release/recover."""

    recovered: bool
    previous_status: str = ""
    rolled_back_to: int = 0
    message: str = ""
