import SwiftUI
import Bedrock
import MijickCamera

// MARK: - Timer Options

enum TimerOption: String, CaseIterable, Identifiable {
    case off = "off"
    case three = "3"
    case five = "5"
    case ten = "10"
    
    var id: String { rawValue }
    
    var displayName: String {
        switch self {
        case .off: return String(localized: "Off")
        case .three: return String(localized: "3s")
        case .five: return String(localized: "5s")
        case .ten: return String(localized: "10s")
        }
    }
    
    var seconds: Int {
        switch self {
        case .off: return 0
        case .three: return 3
        case .five: return 5
        case .ten: return 10
        }
    }
}

// MARK: - Capture Mode

enum CaptureMode: String, CaseIterable, Identifiable {
    case photo = "photo"
    case video = "video"
    case boomerang = "boomerang"
    
    var id: String { rawValue }
    
    var displayName: String {
        switch self {
        case .photo: return String(localized: "Photo")
        case .video: return String(localized: "Video")
        case .boomerang: return String(localized: "Boomerang")
        }
    }
    
    var systemImage: String {
        switch self {
        case .photo: return "camera.fill"
        case .video: return "video.fill"
        case .boomerang: return "arrow.2.squarepath"
        }
    }
    
    var isPremium: Bool {
        switch self {
        case .photo: return false
        case .video, .boomerang: return true
        }
    }
}

// MARK: - Settings ViewModel

/// Observable settings view model with iCloud sync across all devices.
/// Uses Bedrock's CloudSyncManager for automatic synchronization.
/// Premium features are automatically reset to defaults when user doesn't have premium.
@MainActor
@Observable
final class SettingsViewModel: RingLightConfigurable {
    
    // MARK: - Ring Size Limits
    
    /// Minimum ring border size in points
    static let minRingSize: CGFloat = 10
    
    /// Maximum ring border size in points
    static let maxRingSize: CGFloat = 120
    
    /// Default ring border size
    static let defaultRingSize: CGFloat = 40
    
    // MARK: - Premium Manager
    
    /// Premium manager for checking subscription status
    private let premiumManager = PremiumManager()
    
    /// Whether the user has premium access
    var isPremiumUnlocked: Bool { premiumManager.isPremiumUnlocked }
    
    // MARK: - Cloud Sync Manager
    
    /// Manages iCloud sync for settings across all devices
    private let cloudSync = CloudSyncManager<SyncedSettings>()
    
    /// Debounce task for slider values
    private var debounceTask: Task<Void, Never>?
    
    /// Debounce delay for continuous slider updates (in seconds)
    private static let debounceDelay: Duration = .milliseconds(300)
    
    /// Cached ring size for immediate UI updates (before debounced save)
    private var _cachedRingSize: CGFloat?
    
    // MARK: - Observable Properties (Synced)
    
    /// Ring border size in points (debounced save)
    var ringSize: CGFloat {
        get { _cachedRingSize ?? cloudSync.data.ringSize }
        set {
            _cachedRingSize = newValue
            debouncedSave(key: "ringSize") {
                self._cachedRingSize = nil
                self.updateSettings { $0.ringSize = newValue }
            }
        }
    }
    
    /// Cached light color ID for immediate UI updates
    private var _cachedLightColorId: String?
    
    /// Default free color ID for non-premium users
    private static let defaultFreeColorId = "pureWhite"
    
    /// Premium color IDs that require subscription
    private static let premiumColorIds: Set<String> = ["iceBlue", "softPink", "warmAmber", "coolLavender", RingLightColor.customId]
    
    /// ID of the selected light color preset
    var lightColorId: String {
        get {
            let storedId = _cachedLightColorId ?? cloudSync.data.lightColorId
            return PremiumGate.get(storedId, default: Self.defaultFreeColorId, premiumValues: Self.premiumColorIds, isPremium: isPremiumUnlocked)
        }
        set {
            guard PremiumGate.canSet(newValue, premiumValues: Self.premiumColorIds, isPremium: isPremiumUnlocked) else { return }
            _cachedLightColorId = newValue
            updateSettings { $0.lightColorId = newValue }
        }
    }
    
    /// Cached custom color for immediate UI updates
    private var _cachedCustomColor: Color?
    
    /// Custom color for ring light (premium feature, debounced save)
    /// Note: Getter always returns stored value to preserve user's choice if they re-subscribe
    var customColor: Color {
        get {
            _cachedCustomColor ?? Color(
                red: cloudSync.data.customColorRed,
                green: cloudSync.data.customColorGreen,
                blue: cloudSync.data.customColorBlue
            )
        }
        set {
            guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
            _cachedCustomColor = newValue
            let rgb = CustomColorRGB(from: newValue)
            debouncedSave(key: "customColor") {
                self._cachedCustomColor = nil
                self.updateSettings {
                    $0.customColorRed = rgb.red
                    $0.customColorGreen = rgb.green
                    $0.customColorBlue = rgb.blue
                }
            }
        }
    }
    
    /// Whether front flash is enabled (hides preview during capture)
    var isFrontFlashEnabled: Bool {
        get { cloudSync.data.isFrontFlashEnabled }
        set { updateSettings { $0.isFrontFlashEnabled = newValue } }
    }
    
    /// Whether the camera preview is flipped to show a true mirror (PREMIUM)
    var isMirrorFlipped: Bool {
        get { PremiumGate.get(cloudSync.data.isMirrorFlipped, default: false, isPremium: isPremiumUnlocked) }
        set { 
            guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
            updateSettings { $0.isMirrorFlipped = newValue } 
        }
    }
    
    /// Whether skin smoothing filter is enabled (PREMIUM)
    var isSkinSmoothingEnabled: Bool {
        get { PremiumGate.get(cloudSync.data.isSkinSmoothingEnabled, default: false, isPremium: isPremiumUnlocked) }
        set { 
            guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
            updateSettings { $0.isSkinSmoothingEnabled = newValue } 
        }
    }
    
    /// Whether the grid overlay is visible
    var isGridVisible: Bool {
        get { cloudSync.data.isGridVisible }
        set { updateSettings { $0.isGridVisible = newValue } }
    }
    
    /// Current camera zoom factor
    var currentZoomFactor: Double {
        get { cloudSync.data.currentZoomFactor }
        set { updateSettings { $0.currentZoomFactor = newValue } }
    }
    
    /// Whether captures are auto-saved to Photo Library
    var isAutoSaveEnabled: Bool {
        get { cloudSync.data.isAutoSaveEnabled }
        set { updateSettings { $0.isAutoSaveEnabled = newValue } }
    }
    
    // MARK: - Computed Properties
    
    /// Convenience property for border width (same as ringSize)
    var borderWidth: CGFloat { ringSize }
    
    /// Premium timer options that require subscription
    private static let premiumTimerOptions: Set<TimerOption> = [.five, .ten]
    
    /// Selected timer option (5s and 10s are PREMIUM)
    var selectedTimer: TimerOption {
        get { 
            let stored = TimerOption(rawValue: cloudSync.data.selectedTimerRaw) ?? .off
            return PremiumGate.get(stored, default: .three, premiumValues: Self.premiumTimerOptions, isPremium: isPremiumUnlocked)
        }
        set { 
            guard PremiumGate.canSet(newValue, premiumValues: Self.premiumTimerOptions, isPremium: isPremiumUnlocked) else { return }
            updateSettings { $0.selectedTimerRaw = newValue.rawValue } 
        }
    }
    
    var selectedCaptureMode: CaptureMode {
        get { CaptureMode(rawValue: cloudSync.data.selectedCaptureModeRaw) ?? .photo }
        set { updateSettings { $0.selectedCaptureModeRaw = newValue.rawValue } }
    }

    // MARK: - Camera Settings

    var flashMode: CameraFlashMode {
        get { CameraFlashMode(rawValue: cloudSync.data.flashModeRaw) ?? .off }
        set { updateSettings { $0.flashModeRaw = newValue.rawValue } }
    }

    /// Whether flash is synced with ring light color (PREMIUM)
    var isFlashSyncedWithRingLight: Bool {
        get { PremiumGate.get(cloudSync.data.isFlashSyncedWithRingLight, default: false, isPremium: isPremiumUnlocked) }
        set { 
            guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
            updateSettings { $0.isFlashSyncedWithRingLight = newValue } 
        }
    }

    /// HDR mode setting (PREMIUM)
    var hdrMode: CameraHDRMode {
        get { 
            let stored = CameraHDRMode(rawValue: cloudSync.data.hdrModeRaw) ?? .off
            return PremiumGate.get(stored, default: .off, isPremium: isPremiumUnlocked)
        }
        set { 
            guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
            updateSettings { $0.hdrModeRaw = newValue.rawValue } 
        }
    }

    /// Premium photo quality options that require subscription
    private static let premiumPhotoQualities: Set<PhotoQuality> = [.high]

    /// Photo quality setting (high is PREMIUM)
    var photoQuality: PhotoQuality {
        get { 
            let stored = PhotoQuality(rawValue: cloudSync.data.photoQualityRaw) ?? PhotoQuality.high
            return PremiumGate.get(stored, default: .medium, premiumValues: Self.premiumPhotoQualities, isPremium: isPremiumUnlocked)
        }
        set { 
            guard PremiumGate.canSet(newValue, premiumValues: Self.premiumPhotoQualities, isPremium: isPremiumUnlocked) else { return }
            updateSettings { $0.photoQualityRaw = newValue.rawValue } 
        }
    }

    var cameraPosition: CameraPosition {
        get {
            if cloudSync.data.cameraPositionRaw == "front" {
                return .front
            } else {
                return .back
            }
        }
        set {
            updateSettings { $0.cameraPositionRaw = newValue == .front ? "front" : "back" }
        }
    }

    var isRingLightEnabled: Bool {
        get { cloudSync.data.isRingLightEnabled }
        set { updateSettings { $0.isRingLightEnabled = newValue } }
    }

    var ringLightOpacity: Double {
        get { cloudSync.data.ringLightOpacity }
        set { updateSettings { $0.ringLightOpacity = newValue } }
    }

    /// Whether Center Stage is enabled (PREMIUM)
    var isCenterStageEnabled: Bool {
        get { PremiumGate.get(cloudSync.data.isCenterStageEnabled, default: false, isPremium: isPremiumUnlocked) }
        set { 
            guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
            updateSettings { $0.isCenterStageEnabled = newValue } 
        }
    }

    var selectedLightColor: RingLightColor {
        get { RingLightColor.fromId(lightColorId, customColor: customColor) }
        set {
            // Premium check handled by lightColorId and customColor setters
            lightColorId = newValue.id
            if newValue.isCustom {
                customColor = newValue.color
            }
        }
    }
    
    var lightColor: Color {
        if lightColorId == RingLightColor.customId {
            return customColor
        }
        return selectedLightColor.color
    }
    
    /// Whether custom color is currently selected
    var isCustomColorSelected: Bool {
        lightColorId == RingLightColor.customId
    }
    
    /// Sets the custom color and selects it (PREMIUM)
    func selectCustomColor(_ color: Color) {
        guard PremiumGate.canSet(isPremium: isPremiumUnlocked) else { return }
        customColor = color
        lightColorId = RingLightColor.customId
    }
    
    // MARK: - Sync Status
    
    /// Whether iCloud sync is available
    var iCloudAvailable: Bool { cloudSync.iCloudAvailable }
    
    /// Whether iCloud sync is enabled (available to all users)
    var iCloudEnabled: Bool {
        get { cloudSync.iCloudEnabled }
        set { cloudSync.iCloudEnabled = newValue }
    }
    
    /// Last sync date
    var lastSyncDate: Date? { cloudSync.lastSyncDate }
    
    /// Current sync status message
    var syncStatus: String { cloudSync.syncStatus }
    
    /// Whether initial sync has completed
    var hasCompletedInitialSync: Bool { cloudSync.hasCompletedInitialSync }
    
    // MARK: - Initialization
    
    init() {
        // CloudSyncManager handles syncing automatically
    }
    
    // MARK: - Private Methods
    
    /// Updates settings and saves to cloud immediately
    private func updateSettings(_ transform: (inout SyncedSettings) -> Void) {
        cloudSync.update { settings in
            transform(&settings)
            settings.modificationCount += 1
        }
    }
    
    /// Debounces save operations for continuous values like sliders
    private func debouncedSave(key: String, action: @escaping () -> Void) {
        // Cancel any pending debounce
        debounceTask?.cancel()
        
        // Schedule debounced save
        debounceTask = Task {
            try? await Task.sleep(for: Self.debounceDelay)
            
            guard !Task.isCancelled else { return }
            
            action()
        }
    }
    
    // MARK: - Sync Actions
    
    /// Forces a sync with iCloud
    func forceSync() {
        cloudSync.sync()
    }
    
    /// Resets all settings to defaults
    func resetToDefaults() {
        cloudSync.reset()
    }
    
    // MARK: - Validation
    
    var isValidConfiguration: Bool {
        ringSize >= Self.minRingSize
    }
}

// MARK: - CaptureControlling Conformance

extension SettingsViewModel: CaptureControlling {
    func startCountdown() async {
        // Countdown handled by CameraViewModel
    }
    
    func performCapture() {
        // Capture handled by CameraViewModel
    }
    
    func performFlashBurst() async {
        // Flash handled by CameraViewModel
    }
}
