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: List[str] = [] gateway: List[str] = [] subnet: List[str] = [] dns1: List[str] = [] dns2: List[str] = [] 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: str = "" device_melodies_all: List[MelodyMainItem] = [] device_melodies_favorites: List[str] = [] user_list: List[str] = [] websocket_url: str = "" churchAssistantURL: str = "" staffNotes: 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[str] = None 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 class DeviceInDB(DeviceCreate): id: str device_id: str = "" class DeviceListResponse(BaseModel): devices: List[DeviceInDB] total: int 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