from pydantic import BaseModel
from typing import Optional, List
from enum import Enum


class UpdateType(str, Enum):
    optional  = "optional"   # user-initiated only
    mandatory = "mandatory"  # auto-installs on next reboot
    emergency = "emergency"  # auto-installs on reboot + daily check + MQTT push


class FirmwareVersion(BaseModel):
    id: str
    hw_type: str              # e.g. "vesper", "vesper_plus", "vesper_pro", "bespoke"
    channel: str              # "stable", "beta", "alpha", "testing"
    version: str              # semver e.g. "1.5"
    filename: str
    size_bytes: int
    sha256: str
    update_type: UpdateType = UpdateType.mandatory
    min_fw_version: Optional[str] = None  # minimum fw version required to install this
    uploaded_at: str
    changelog: Optional[str] = None
    release_note: Optional[str] = None
    is_latest: bool = False
    bespoke_uid: Optional[str] = None    # only set when hw_type == "bespoke"


class FirmwareListResponse(BaseModel):
    firmware: List[FirmwareVersion]
    total: int


class FirmwareMetadataResponse(BaseModel):
    """Returned by both /latest and /{version}/info endpoints.

    Two orthogonal axes:
      channel     — the release track the device is subscribed to
                    ("stable" | "beta" | "development")
                    Firmware validates this matches the channel it requested.
      update_type — the urgency of THIS release, set by the publisher
                    ("optional" | "mandatory" | "emergency")
                    Firmware reads mandatory/emergency booleans derived from this.

    Additional firmware-compatible fields:
      size        — binary size in bytes (firmware reads "size", not "size_bytes")
      mandatory   — True when update_type is mandatory or emergency
      emergency   — True only when update_type is emergency
    """
    hw_type: str
    channel: str                       # release track — firmware validates this
    version: str
    size: int                          # firmware reads "size"
    size_bytes: int                    # kept for admin-panel consumers
    sha256: str
    update_type: UpdateType            # urgency enum — for admin panel display
    mandatory: bool                    # derived: update_type in (mandatory, emergency)
    emergency: bool                    # derived: update_type == emergency
    min_fw_version: Optional[str] = None
    download_url: str
    uploaded_at: str
    release_note: Optional[str] = None


# Keep backwards-compatible alias
FirmwareLatestResponse = FirmwareMetadataResponse
