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

import Foundation
import UserNotifications
import Observation

/// Service to handle Focus mode interactions and ensure app functionality
@Observable
class FocusModeService {
    
    // MARK: - Singleton
    static let shared = FocusModeService()
    
    // MARK: - Properties
    private(set) var isFocusModeActive = false
    private(set) var currentFocusMode: String?
    private var focusModeObserver: NSObjectProtocol?
    
    // MARK: - Initialization
    private init() {
        setupFocusModeMonitoring()
    }
    
    deinit {
        removeFocusModeObserver()
    }
    
    // MARK: - Public Interface
    
    /// Check if Focus mode is currently active
    var isActive: Bool {
        return isFocusModeActive
    }
    
    /// Get the current Focus mode name if available
    var activeFocusMode: String? {
        return currentFocusMode
    }
    
    /// 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()
            }
            
            return granted
        } catch {
            print("❌ 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])
        
        print("🔔 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
    ) {
        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
            print("🔔 Using default notification sound")
        } else {
            content.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: soundName))
            print("🔔 Using custom alarm sound: \(soundName)")
            print("🔔 Sound file should be in main bundle: \(soundName)")
        }
        content.categoryIdentifier = "ALARM_CATEGORY"
        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 {
                print("❌ Error scheduling alarm notification: \(error)")
            } else {
                print("🔔 Alarm notification scheduled for \(date)")
            }
        }
    }
    
    /// Cancel alarm notification
    func cancelAlarmNotification(identifier: String) {
        UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [identifier])
        print("🔔 Cancelled alarm notification: \(identifier)")
    }
    
    /// Cancel all alarm notifications
    func cancelAllAlarmNotifications() {
        UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
        print("🔔 Cancelled all alarm notifications")
    }
    
    // MARK: - Private Methods
    
    /// Set up monitoring for Focus mode changes
    private func setupFocusModeMonitoring() {
        // Monitor notification center for Focus mode changes
        focusModeObserver = NotificationCenter.default.addObserver(
            forName: .NSSystemTimeZoneDidChange,
            object: nil,
            queue: .main
        ) { [weak self] _ in
            self?.updateFocusModeStatus()
        }
        
        // Initial status check
        updateFocusModeStatus()
    }
    
    /// Remove Focus mode observer
    private func removeFocusModeObserver() {
        if let observer = focusModeObserver {
            NotificationCenter.default.removeObserver(observer)
            focusModeObserver = nil
        }
    }
    
    /// Update Focus mode status
    private func updateFocusModeStatus() {
        // Check if Focus mode is active by examining notification settings
        UNUserNotificationCenter.current().getNotificationSettings { settings in
            DispatchQueue.main.async {
                // This is a simplified check - in a real implementation,
                // you might need to use private APIs or other methods
                // to detect Focus mode status
                self.isFocusModeActive = settings.authorizationStatus == .authorized
                self.currentFocusMode = self.isFocusModeActive ? "Active" : nil
                
                if self.isFocusModeActive {
                    print("🎯 Focus mode is active")
                } else {
                    print("🎯 Focus mode is not active")
                }
            }
        }
    }
    
    /// 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()
        }
        
        print("🎯 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.
        """
    }
}
