"""
Sovereign Orchestrator - Pydantic Models

Data models for API request/response payloads and internal state.
"""

from __future__ import annotations

import uuid
from datetime import datetime, timezone
from enum import Enum
from typing import Optional

from pydantic import BaseModel, Field


# ---------------------------------------------------------------------------
# Enums
# ---------------------------------------------------------------------------

class BuildState(str, Enum):
    """Lifecycle states for an ISO build job."""
    PENDING = "pending"
    BUILDING = "building"
    UPLOADING = "uploading"
    COMPLETED = "completed"
    FAILED = "failed"


class NetworkSource(str, Enum):
    """Proxmox installer network source options."""
    FROM_DHCP = "from-dhcp"
    FROM_ANSWER = "from-answer"


class Filesystem(str, Enum):
    """Supported root filesystems."""
    EXT4 = "ext4"
    XFS = "xfs"
    ZFS = "zfs"
    BTRFS = "btrfs"


# ---------------------------------------------------------------------------
# Request models
# ---------------------------------------------------------------------------

class ISOConfig(BaseModel):
    """Configuration payload for generating a custom auto-install ISO."""

    fqdn: str = Field(
        ..., description="Fully qualified domain name for the new host",
        examples=["pve-test.internal.718it.biz"],
    )
    keyboard: str = Field(default="en-us", description="Keyboard layout")
    country: str = Field(default="us", description="Country code")
    timezone: str = Field(
        default="America/New_York", description="Timezone string"
    )
    mailto: str = Field(
        default="wmantly@gmail.com", description="Admin email address"
    )
    root_password: str = Field(
        ..., description="Root password for the installed system"
    )
    root_ssh_keys: list[str] = Field(
        default_factory=list,
        description="SSH public keys to authorize for root",
    )
    network_source: NetworkSource = Field(
        default=NetworkSource.FROM_DHCP,
        description="Network configuration source",
    )
    filesystem: Filesystem = Field(
        default=Filesystem.EXT4, description="Root filesystem type"
    )
    disk_list: list[str] = Field(
        default_factory=lambda: ["sda"],
        description="Disks to use for installation",
    )
    reboot_on_error: bool = Field(
        default=False, description="Reboot automatically on install error"
    )


class DeployConfig(BaseModel):
    """Configuration for deploying a VM with the custom ISO."""

    vmid: int = Field(default=900, description="VM ID to create")
    node: str = Field(default="dl380-0", description="Proxmox node name")
    cores: int = Field(default=4, ge=1, le=128, description="CPU cores")
    memory: int = Field(
        default=8192, ge=512, description="Memory in MiB"
    )
    disk_size: str = Field(
        default="128G", description="Root disk size (e.g. 128G)"
    )
    build_id: Optional[str] = Field(
        default=None,
        description="Build ID whose ISO to use. Defaults to latest.",
    )
    storage: str = Field(
        default="local-lvm", description="Proxmox storage for the VM disk"
    )
    iso_storage: str = Field(
        default="local", description="Proxmox storage containing ISOs"
    )
    bridge: str = Field(
        default="vmbr1", description="Network bridge to attach the VM to"
    )


# ---------------------------------------------------------------------------
# Internal / response models
# ---------------------------------------------------------------------------

class BuildStatus(BaseModel):
    """Tracks the state of an ISO build job."""

    id: str = Field(default_factory=lambda: uuid.uuid4().hex[:12])
    state: BuildState = BuildState.PENDING
    iso_config: Optional[ISOConfig] = None
    iso_filename: Optional[str] = None
    logs: list[str] = Field(default_factory=list)
    created_at: datetime = Field(
        default_factory=lambda: datetime.now(timezone.utc)
    )
    updated_at: datetime = Field(
        default_factory=lambda: datetime.now(timezone.utc)
    )
    error: Optional[str] = None

    def log(self, message: str) -> None:
        """Append a timestamped log line."""
        ts = datetime.now(timezone.utc).isoformat()
        self.logs.append(f"[{ts}] {message}")
        self.updated_at = datetime.now(timezone.utc)


class VMStatus(BaseModel):
    """Proxmox VM status snapshot."""

    vmid: int
    name: Optional[str] = None
    status: str
    node: str
    cpus: Optional[int] = None
    maxmem: Optional[int] = None
    maxdisk: Optional[int] = None
    uptime: Optional[int] = None
    pid: Optional[int] = None


class NodeInfo(BaseModel):
    """Proxmox node summary."""

    node: str
    status: str
    cpu: Optional[float] = None
    maxcpu: Optional[int] = None
    mem: Optional[int] = None
    maxmem: Optional[int] = None
    uptime: Optional[int] = None


class ISOInfo(BaseModel):
    """ISO file metadata."""

    volid: str
    filename: str
    size: Optional[int] = None


class SystemStatus(BaseModel):
    """Aggregate system status returned by /api/status."""

    nodes: list[NodeInfo] = Field(default_factory=list)
    test_vm: Optional[VMStatus] = None
    available_isos: list[ISOInfo] = Field(default_factory=list)
    active_builds: list[BuildStatus] = Field(default_factory=list)
    proxmox_connected: bool = False
    error: Optional[str] = None


class DeployResult(BaseModel):
    """Response from a deploy operation."""

    vmid: int
    node: str
    status: str
    message: str
    task_id: Optional[str] = None
