//
//  AlarmService.swift
//  TheNoiseClock
//
//  Created by Matt Bruce on 9/7/25.
//
//  NOTE: This service now only handles alarm persistence.
//  Alarm scheduling is handled by AlarmKitService (iOS 26+).
//  The old notification scheduling code has been removed.
//

import Foundation
import Observation
import Bedrock

/// Service for managing alarm persistence.
/// Alarm scheduling is handled by AlarmKitService.
@Observable
class AlarmService {
    
    // MARK: - Properties
    private(set) var alarms: [Alarm] = []
    private var alarmLookup: [UUID: Int] = [:]
    private var persistenceWorkItem: DispatchWorkItem?
    
    // MARK: - Initialization
    init() {
        loadAlarms()
        Design.debugLog("[alarms] AlarmService initialized with \(alarms.count) alarms")
    }
    
    // MARK: - Public Interface
    
    /// Add an alarm to storage. Does NOT schedule - caller should use AlarmKitService.
    func addAlarm(_ alarm: Alarm) {
        Design.debugLog("[alarms] AlarmService.addAlarm: \(alarm.label) at \(alarm.time)")
        alarms.append(alarm)
        updateAlarmLookup()
        saveAlarms()
    }
    
    /// Update an alarm in storage. Does NOT reschedule - caller should use AlarmKitService.
    func updateAlarm(_ alarm: Alarm) {
        guard let index = alarmLookup[alarm.id] else {
            Design.debugLog("[alarms] AlarmService.updateAlarm: alarm not found \(alarm.id)")
            return
        }
        Design.debugLog("[alarms] AlarmService.updateAlarm: \(alarm.label) enabled=\(alarm.isEnabled)")
        alarms[index] = alarm
        updateAlarmLookup()
        saveAlarms()
    }
    
    /// Delete an alarm from storage. Does NOT cancel - caller should use AlarmKitService.
    func deleteAlarm(id: UUID) {
        Design.debugLog("[alarms] AlarmService.deleteAlarm: \(id)")
        alarms.removeAll { $0.id == id }
        updateAlarmLookup()
        saveAlarms()
    }
    
    /// Toggle an alarm's enabled state. Does NOT reschedule - caller should use AlarmKitService.
    func toggleAlarm(id: UUID) {
        guard let index = alarmLookup[id] else { return }
        alarms[index].isEnabled.toggle()
        Design.debugLog("[alarms] AlarmService.toggleAlarm: \(id) now enabled=\(alarms[index].isEnabled)")
        saveAlarms()
    }
    
    func getAlarm(id: UUID) -> Alarm? {
        return alarms.first { $0.id == id }
    }
    
    // MARK: - Private Methods
    private func updateAlarmLookup() {
        alarmLookup.removeAll()
        for (index, alarm) in alarms.enumerated() {
            alarmLookup[alarm.id] = index
        }
    }
    
    private func saveAlarms() {
        persistenceWorkItem?.cancel()
        
        let alarmsSnapshot = self.alarms
        let work = DispatchWorkItem {
            if let encoded = try? JSONEncoder().encode(alarmsSnapshot) {
                UserDefaults.standard.set(encoded, forKey: AppConstants.StorageKeys.savedAlarms)
            }
        }
        persistenceWorkItem = work
        
        DispatchQueue.main.asyncAfter(
            deadline: .now() + AppConstants.PersistenceDelays.alarms,
            execute: work
        )
    }
    
    private func loadAlarms() {
        if let savedAlarms = UserDefaults.standard.data(forKey: AppConstants.StorageKeys.savedAlarms),
           let decodedAlarms = try? JSONDecoder().decode([Alarm].self, from: savedAlarms) {
            // Migrate sound file extensions from .caf to .mp3
            alarms = decodedAlarms.map { alarm in
                var migratedAlarm = alarm
                migratedAlarm.soundName = migrateSoundName(alarm.soundName)
                return migratedAlarm
            }
            updateAlarmLookup()
            Design.debugLog("[alarms] Loaded \(alarms.count) alarms from storage")
            
            // Save migrated alarms if any changes were made
            let needsMigration = zip(decodedAlarms, alarms).contains { $0.soundName != $1.soundName }
            if needsMigration {
                Design.debugLog("[alarms] Sound file migration applied, saving...")
                saveAlarms()
            }
            // Note: AlarmKit scheduling is handled by AlarmViewModel.rescheduleAllAlarms()
        }
    }
    
    /// Migrate sound file names from .caf to .mp3
    private func migrateSoundName(_ soundName: String) -> String {
        if soundName.hasSuffix(".caf") {
            let migrated = soundName.replacingOccurrences(of: ".caf", with: ".mp3")
            Design.debugLog("[alarms] Migrating sound: \(soundName) -> \(migrated)")
            return migrated
        }
        return soundName
    }
    
    /// Get all enabled alarms (for rescheduling with AlarmKit)
    func getEnabledAlarms() -> [Alarm] {
        return alarms.filter { $0.isEnabled }
    }
}
