from pydantic import BaseModel, Field
from typing import Optional, List, Any, Dict
from enum import Enum


class LogLevel(str, Enum):
    INFO = "INFO"
    WARN = "WARN"
    ERROR = "ERROR"


class CommandStatus(str, Enum):
    PENDING = "pending"
    SUCCESS = "success"
    ERROR = "error"
    TIMEOUT = "timeout"


class MqttCommandRequest(BaseModel):
    cmd: str = Field(..., description="Command name: ping, playback, file_manager, relay_setup, clock_setup, system_info, system")
    contents: Dict[str, Any] = Field(default_factory=dict, description="Command payload contents")


class DeviceLogEntry(BaseModel):
    id: int
    device_serial: str
    level: str
    message: str
    device_timestamp: Optional[int] = None
    received_at: str


class HeartbeatEntry(BaseModel):
    id: int
    device_serial: str
    device_id: Optional[str] = None
    firmware_version: Optional[str] = None
    ip_address: Optional[str] = None
    gateway: Optional[str] = None
    uptime_ms: Optional[int] = None
    uptime_display: Optional[str] = None
    received_at: str


class CommandEntry(BaseModel):
    id: int
    device_serial: str
    command_name: str
    command_payload: Optional[str] = None
    status: str
    response_payload: Optional[str] = None
    sent_at: str
    responded_at: Optional[str] = None


class DeviceMqttStatus(BaseModel):
    device_serial: str
    online: bool
    last_heartbeat: Optional[HeartbeatEntry] = None
    seconds_since_heartbeat: Optional[int] = None


class MqttStatusResponse(BaseModel):
    devices: List[DeviceMqttStatus]
    broker_connected: bool = False


class LogListResponse(BaseModel):
    logs: List[DeviceLogEntry]
    total: int


class HeartbeatListResponse(BaseModel):
    heartbeats: List[HeartbeatEntry]
    total: int


class CommandListResponse(BaseModel):
    commands: List[CommandEntry]
    total: int


class CommandSendResponse(BaseModel):
    success: bool
    command_id: int
    message: str


class DeviceAlertEntry(BaseModel):
    device_serial: str
    subsystem: str
    state: str
    message: Optional[str] = None
    updated_at: str


class DeviceAlertsResponse(BaseModel):
    alerts: List[DeviceAlertEntry]
