//
//  FocusModeService.swift
//  TheNoiseClock
//
//  Created by Matt Bruce on 9/7/25.
//

import Foundation
import Observation
import UIKit
import UserNotifications
import Bedrock

/// Service to align notifications with Focus mode behavior
@Observable
class FocusModeService {
    
    // MARK: - Singleton
    static let shared = FocusModeService()
    
    // MARK: - Properties
    private(set) var notificationAuthorizationStatus: UNAuthorizationStatus = .notDetermined
    private(set) var timeSensitiveSetting: UNNotificationSetting = .notSupported
    private(set) var scheduledDeliverySetting: UNNotificationSetting = .notSupported
    private var notificationSettingsObserver: NSObjectProtocol?
    
    // MARK: - Initialization
    private init() {
        setupFocusModeMonitoring()
    }
    
    deinit {
        removeFocusModeObserver()
    }
    
    // MARK: - Public Interface
    
    /// Check if Focus mode is currently active
    var isAuthorized: Bool {
        notificationAuthorizationStatus == .authorized
    }
    
    /// Request notification permissions that work with Focus modes
    func requestNotificationPermissions() async -> Bool {
        do {
            let granted = try await UNUserNotificationCenter.current().requestAuthorization(
                options: [.alert, .sound, .badge, .provisional]
            )
            
            if granted {
                // Configure notification settings for Focus mode compatibility
                await configureNotificationSettings()
            }
            
            await refreshNotificationSettings()
            
            return granted
        } catch {
            Design.debugLog("[general] Error requesting notification permissions: \(error)")
            return false
        }
    }
    
    /// Configure notification settings to work with Focus modes
    private func configureNotificationSettings() async {
        // Create notification categories that work with Focus modes
        let alarmCategory = UNNotificationCategory(
            identifier: "ALARM_CATEGORY",
            actions: [
                UNNotificationAction(
                    identifier: "SNOOZE_ACTION",
                    title: "Snooze",
                    options: []
                ),
                UNNotificationAction(
                    identifier: "STOP_ACTION",
                    title: "Stop",
                    options: [.destructive]
                )
            ],
            intentIdentifiers: [],
            options: [.customDismissAction]
        )
        
        // Register the category
        UNUserNotificationCenter.current().setNotificationCategories([alarmCategory])
        
        Design.debugLog("[settings] Notification settings configured for Focus mode compatibility")
    }
    
    /// Schedule alarm notification with Focus mode awareness
    func scheduleAlarmNotification(
        identifier: String,
        title: String,
        body: String,
        date: Date,
        soundName: String,
        repeats: Bool = false,
        respectFocusModes: Bool = true
    ) {
        let content = UNMutableNotificationContent()
        content.title = title
        content.body = body
        // Use the sound name directly since sounds.json now references CAF files
        if soundName == "default" {
            content.sound = UNNotificationSound.default
            Design.debugLog("[settings] Using default notification sound")
        } else {
            content.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: soundName))
            Design.debugLog("[settings] Using custom alarm sound: \(soundName)")
            Design.debugLog("[settings] Sound file should be in main bundle: \(soundName)")
        }
        content.categoryIdentifier = "ALARM_CATEGORY"
        
        if !respectFocusModes, timeSensitiveSetting == .enabled {
            content.interruptionLevel = .timeSensitive
        }
        content.userInfo = [
            "alarmId": identifier,
            "soundName": soundName,
            "repeats": repeats
        ]
        
        // Create trigger
        let trigger: UNNotificationTrigger
        if repeats {
            let calendar = Calendar.current
            let components = calendar.dateComponents([.hour, .minute], from: date)
            trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true)
        } else {
            // Use calendar trigger for one-time alarms to avoid time interval issues
            let calendar = Calendar.current
            let components = calendar.dateComponents([.hour, .minute], from: date)
            trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: false)
        }
        
        // Create request
        let request = UNNotificationRequest(
            identifier: identifier,
            content: content,
            trigger: trigger
        )
        
        // Schedule notification
        UNUserNotificationCenter.current().add(request) { error in
            if let error = error {
                Design.debugLog("[general] Error scheduling alarm notification: \(error)")
            } else {
                Design.debugLog("[settings] Alarm notification scheduled for \(date)")
            }
        }
    }
    
    /// Cancel alarm notification
    func cancelAlarmNotification(identifier: String) {
        UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [identifier])
        Design.debugLog("[settings] Cancelled alarm notification: \(identifier)")
    }
    
    /// Cancel all alarm notifications
    func cancelAllAlarmNotifications() {
        UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
        Design.debugLog("[settings] Cancelled all alarm notifications")
    }
    
    // MARK: - Private Methods
    
    /// Set up monitoring for Focus mode changes
    private func setupFocusModeMonitoring() {
        notificationSettingsObserver = NotificationCenter.default.addObserver(
            forName: UIApplication.willEnterForegroundNotification,
            object: nil,
            queue: .main
        ) { [weak self] _ in
            Task { await self?.refreshNotificationSettings() }
        }
        
        Task { await refreshNotificationSettings() }
    }
    
    /// Remove Focus mode observer
    private func removeFocusModeObserver() {
        if let observer = notificationSettingsObserver {
            NotificationCenter.default.removeObserver(observer)
            notificationSettingsObserver = nil
        }
    }
    
    /// Refresh notification settings to align with Focus mode behavior.
    @MainActor
    func refreshNotificationSettings() async {
        let settings = await UNUserNotificationCenter.current().notificationSettings()
        notificationAuthorizationStatus = settings.authorizationStatus
        timeSensitiveSetting = settings.timeSensitiveSetting
        scheduledDeliverySetting = settings.scheduledDeliverySetting
        
        Design.debugLog("[settings] Notification settings updated: auth=\(settings.authorizationStatus), timeSensitive=\(settings.timeSensitiveSetting), scheduledDelivery=\(settings.scheduledDeliverySetting)")
    }
    
    /// Get notification authorization status
    func getNotificationAuthorizationStatus() async -> UNAuthorizationStatus {
        let settings = await UNUserNotificationCenter.current().notificationSettings()
        return settings.authorizationStatus
    }
    
    /// Check if notifications are allowed in current Focus mode
    func areNotificationsAllowed() async -> Bool {
        let status = await getNotificationAuthorizationStatus()
        return status == .authorized
    }
}

// MARK: - Focus Mode Configuration
extension FocusModeService {
    
    /// Configure app to work optimally with Focus modes
    func configureForFocusModes() {
        // Set up notification categories that work well with Focus modes
        Task {
            await configureNotificationSettings()
        }
        
        Design.debugLog("[settings] App configured for Focus mode compatibility")
    }
    
    /// Provide user guidance for Focus mode settings
    func getFocusModeGuidance() -> String {
        return """
        For the best experience with TheNoiseClock:
        
        1. Allow notifications in your Focus mode settings
        2. Enable "Time Sensitive" notifications for alarms
        3. Consider adding TheNoiseClock to your Focus mode allowlist
        
        This ensures alarms will work even when Focus mode is active.
        """
    }
}
