from __future__ import annotations from datetime import date from enum import Enum from pydantic import BaseModel, Field, field_validator class LogStatus(str, Enum): taken = "taken" missed = "missed" snoozed = "snoozed" class PinLogin(BaseModel): pin: str = Field( ..., min_length=3, max_length=12, description="Login-PIN, wie in APP_PIN hinterlegt.", ) class LogEntry(BaseModel): slot_id: str = Field( ..., min_length=1, max_length=64, description="ID des Medikamenten-Slots, z.B. 'morning'.", ) status: LogStatus = Field( default=LogStatus.taken, description="Status der Einnahme: taken, missed oder snoozed.", ) day: date | None = Field( default=None, description="Optional: Tag im ISO-Format (YYYY-MM-DD). Standard ist heute.", ) logged_at: str | None = Field( default=None, description="Optional: Zeitstempel im ISO-Format. Standard ist jetzt (UTC).", ) source: str = Field( default="app", description="Herkunft des Logs, z.B. 'app', 'widget' oder 'voice'.", ) class SnoozeRequest(BaseModel): slot_id: str = Field( ..., min_length=1, max_length=64, description="ID des Slots, der verschoben werden soll.", ) minutes: int = Field( ..., description="Snooze-Dauer in Minuten. Erlaubt: 15 oder 30.", ) @field_validator("minutes") @classmethod def allowed_snooze(cls, v: int) -> int: if v not in (15, 30): raise ValueError("minutes must be 15 or 30") return v class PushSubscribe(BaseModel): subscription: dict = Field( ..., description="Web-Push-Subscription-Objekt vom Browser (PushManager.subscribe).", ) class AgentLogEntry(BaseModel): slot_id: str = Field( ..., min_length=1, max_length=64, description="ID des Medikamenten-Slots, z.B. 'morning'.", ) status: LogStatus = Field( default=LogStatus.taken, description="Status der Einnahme: taken, missed oder snoozed.", ) day: date | None = Field( default=None, description="Optional: Tag im ISO-Format (YYYY-MM-DD). Standard ist heute.", ) logged_at: str | None = Field( default=None, description="Optional: Zeitstempel im ISO-Format. Standard ist jetzt (UTC).", ) source: str = Field( default="agent", description="Herkunft des Logs, z.B. 'agent', 'voice' oder 'watch'.", ) class AgentNotifyRequest(BaseModel): title: str = Field( ..., min_length=1, max_length=120, description="Titel der Push-Benachrichtigung.", ) body: str = Field( ..., min_length=1, max_length=512, description="Textkörper der Push-Benachrichtigung.", ) slot_id: str | None = Field( default=None, description="Optional: zugehörige Slot-ID, wird an den Client weitergegeben.", ) tag: str | None = Field( default=None, description="Optional: Notification-Tag für das Ersetzen älterer Notifications.", )