import Foundation /// Einstellungen fuer Ablauf-Benachrichtigungen - je Server eigene. /// /// Rein auf dem Geraet gespeichert (UserDefaults), nicht am Server: Es ist eine /// Einstellung dieser App auf diesem iPhone, kein geteilter Serverzustand. /// Die Einheit, in der „X vor Ablauf" gemeint ist. enum LeadUnit: String, Codable, CaseIterable { case days, weeks var label: String { self == .weeks ? "Wochen" : "Tage" } } /// Eine Erinnerungsregel: „X Tage/Wochen vor Ablauf", optional nur fuer eine /// Kategorie, einmalig oder taeglich wiederkehrend. struct NotificationRule: Codable, Identifiable, Equatable { let id: UUID var amount: Int var unit: LeadUnit /// nil = alle Kategorien (die allgemeine Regel). var categoryId: Int? /// true = das Produkt taucht jeden Tag im Fenster (ab „X vorher" bis Ablauf) /// in der Tagesmeldung auf; false = nur am Tag „X vorher". var recurring: Bool init(id: UUID = UUID(), amount: Int = 3, unit: LeadUnit = .days, categoryId: Int? = nil, recurring: Bool = false) { self.id = id self.amount = amount self.unit = unit self.categoryId = categoryId self.recurring = recurring } /// Vorlaufzeit in Tagen - Wochen werden umgerechnet. var leadDays: Int { unit == .weeks ? amount * 7 : amount } } /// Alle Benachrichtigungseinstellungen eines Servers. struct ServerNotificationConfig: Codable, Equatable { var enabled: Bool = false /// Uhrzeit der Tagesmeldung. var hour: Int = 9 var minute: Int = 0 /// Letzte Warnung am Ablauftag („ACHTUNG: … abgelaufen"), fuer alle Produkte. var lastWarningOnExpiry: Bool = true var rules: [NotificationRule] = [] /// Ohne aktive Regel und ohne letzte Warnung gibt es nichts zu planen. var hasSomethingToSchedule: Bool { enabled && (!rules.isEmpty || lastWarningOnExpiry) } } /// Liest und schreibt die Konfigurationen. Ein Woerterbuch je Profil-UUID, /// analog zu `ProfileStore`. enum NotificationStore { static let key = "notification_configs" static func loadAll() -> [String: ServerNotificationConfig] { guard let data = UserDefaults.standard.data(forKey: key), let dict = try? JSONDecoder().decode([String: ServerNotificationConfig].self, from: data) else { return [:] } return dict } static func config(for profileID: UUID) -> ServerNotificationConfig { loadAll()[profileID.uuidString] ?? ServerNotificationConfig() } static func save(_ config: ServerNotificationConfig, for profileID: UUID) { var alle = loadAll() alle[profileID.uuidString] = config guard let data = try? JSONEncoder().encode(alle) else { return } UserDefaults.standard.set(data, forKey: key) } /// Beim Loeschen eines Profils die zugehoerige Konfiguration mit entfernen. static func remove(for profileID: UUID) { var alle = loadAll() alle.removeValue(forKey: profileID.uuidString) guard let data = try? JSONEncoder().encode(alle) else { return } UserDefaults.standard.set(data, forKey: key) } }