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


# --- Enums ---

class HelperMelodyTypes(str, Enum):
    orthodox = "orthodox"
    catholic = "catholic"
    all = "all"


class HelperRingAlerts(str, Enum):
    disabled = "disabled"
    single = "single"
    multi = "multi"


class DeviceTiers(str, Enum):
    basic = "basic"
    small = "small"
    mini = "mini"
    premium = "premium"
    vip = "vip"
    custom = "custom"


# --- Nested Structs ---

class DeviceNetworkSettings(BaseModel):
    hostname: str = ""
    useStaticIP: bool = False
    ipAddress: Any = []
    gateway: Any = []
    subnet: Any = []
    dns1: Any = []
    dns2: Any = []


class DeviceClockSettings(BaseModel):
    clockOutputs: List[int] = []
    clockTimings: List[int] = []
    ringAlertsMasterOn: bool = False
    ringAlerts: HelperRingAlerts = HelperRingAlerts.disabled
    ringIntervals: int = 0
    hourAlertsBell: int = 0
    halfhourAlertsBell: int = 0
    quarterAlertsBell: int = 0
    isDaySilenceOn: bool = False
    isNightSilenceOn: bool = False
    daySilenceFrom: str = ""
    daySilenceTo: str = ""
    nightSilenceFrom: str = ""
    nightSilenceTo: str = ""
    backlightTurnOnTime: str = ""
    backlightTurnOffTime: str = ""
    isBacklightAutomationOn: bool = False
    backlightOutput: int = 0


class DeviceAttributes(BaseModel):
    hasAssistant: bool = False
    hasClock: bool = False
    hasBells: bool = False
    totalBells: int = 0
    bellOutputs: List[int] = []
    hammerTimings: List[int] = []
    bellGuardOn: bool = False
    bellGuardSafetyOn: bool = False
    warningsOn: bool = False
    towerClockTime: str = ""
    clockSettings: DeviceClockSettings = DeviceClockSettings()
    deviceLocale: HelperMelodyTypes = HelperMelodyTypes.all
    networkSettings: DeviceNetworkSettings = DeviceNetworkSettings()
    serialLogLevel: int = 0
    sdLogLevel: int = 0
    mqttLogLevel: int = 0


class DeviceSubInformation(BaseModel):
    subscrTier: DeviceTiers = DeviceTiers.basic
    subscrStart: str = ""
    subscrDuration: int = 0
    maxUsers: int = 0
    maxOutputs: int = 0


class DeviceStatistics(BaseModel):
    totalPlaybacks: int = 0
    totalHammerStrikes: int = 0
    perBellStrikes: List[int] = []
    totalWarningsGiven: int = 0
    warrantyActive: bool = False
    warrantyStart: str = ""
    warrantyPeriod: int = 0
    maintainedOn: str = ""
    maintainancePeriod: int = 0


class MelodyMainItem(BaseModel):
    """Mirrors the Melody schema used in the melodies collection."""
    information: dict = {}
    default_settings: dict = {}
    type: str = ""
    url: str = ""
    uid: str = ""
    pid: str = ""


# --- Request / Response schemas ---

class DeviceCreate(BaseModel):
    device_name: str = ""
    device_photo: str = ""
    device_location: str = ""
    is_Online: bool = False
    device_attributes: DeviceAttributes = DeviceAttributes()
    device_subscription: DeviceSubInformation = DeviceSubInformation()
    device_stats: DeviceStatistics = DeviceStatistics()
    events_on: bool = False
    device_location_coordinates: Any = None  # GeoPoint dict {lat, lng} or legacy str
    device_melodies_all: List[MelodyMainItem] = []
    device_melodies_favorites: List[str] = []
    user_list: List[str] = []
    websocket_url: str = ""
    churchAssistantURL: str = ""
    staffNotes: str = ""
    hw_family: str = ""
    hw_revision: str = ""
    tags: List[str] = []
    serial_number: str = ""
    customer_id: str = ""
    mfg_status: str = ""


class DeviceUpdate(BaseModel):
    device_name: Optional[str] = None
    device_photo: Optional[str] = None
    device_location: Optional[str] = None
    is_Online: Optional[bool] = None
    # Use raw dicts so only the fields actually sent are present — no Pydantic defaults
    device_attributes: Optional[Dict[str, Any]] = None
    device_subscription: Optional[Dict[str, Any]] = None
    device_stats: Optional[Dict[str, Any]] = None
    events_on: Optional[bool] = None
    device_location_coordinates: Optional[Any] = None  # dict {lat, lng} or legacy str
    device_melodies_all: Optional[List[MelodyMainItem]] = None
    device_melodies_favorites: Optional[List[str]] = None
    user_list: Optional[List[str]] = None
    websocket_url: Optional[str] = None
    churchAssistantURL: Optional[str] = None
    staffNotes: Optional[str] = None
    hw_family: Optional[str] = None
    hw_revision: Optional[str] = None
    tags: Optional[List[str]] = None
    customer_id: Optional[str] = None
    mfg_status: Optional[str] = None


class DeviceInDB(DeviceCreate):
    id: str
    # Legacy field — kept for backwards compat; new docs use serial_number
    device_id: str = ""


class DeviceListResponse(BaseModel):
    devices: List[DeviceInDB]
    total: int


class DeviceNoteCreate(BaseModel):
    content: str
    created_by: str = ""


class DeviceNoteUpdate(BaseModel):
    content: str


class DeviceUserInfo(BaseModel):
    """User info resolved from device_users sub-collection or user_list."""
    user_id: str = ""
    display_name: str = ""
    email: str = ""
    role: str = ""
    photo_url: str = ""


class DeviceUsersResponse(BaseModel):
    users: List[DeviceUserInfo]
    total: int
