import Foundation

@Observable
final class AppSettings {
    private static let selectedTypeIDsKey   = "hp_selectedTypeIDs"
    static let adaptiveTimeoutsEnabledKey = "hp_adaptiveTimeoutsEnabled"
    static let simplifiedUIModeEnabledKey = "hp_simplifiedUIModeEnabled"
    static let typeDetailCacheBackfillVersionKey = "hp_typeDetailCacheBackfillVersion"
    static let currentTypeDetailCacheBackfillVersion = 2

    var selectedTypeIDs: Set<String> {
        didSet { persistTypes() }
    }

    var adaptiveTimeoutsEnabled: Bool {
        didSet {
            UserDefaults.standard.set(adaptiveTimeoutsEnabled, forKey: Self.adaptiveTimeoutsEnabledKey)
        }
    }

    var simplifiedUIModeEnabled: Bool {
        didSet {
            UserDefaults.standard.set(simplifiedUIModeEnabled, forKey: Self.simplifiedUIModeEnabledKey)
        }
    }

    static var currentDeviceID: String {
        KeychainService.resolveDeviceID(swiftDataStoreIsEmpty: false).id
    }

    init() {
        if let data = UserDefaults.standard.data(forKey: Self.selectedTypeIDsKey),
           let ids  = try? JSONDecoder().decode([String].self, from: data) {
            selectedTypeIDs = Set(ids)
        } else {
            selectedTypeIDs = Set(HealthKitService.allTypes.filter { $0.isEnabledByDefault }.map { $0.id })
        }

        if UserDefaults.standard.object(forKey: Self.adaptiveTimeoutsEnabledKey) == nil {
            adaptiveTimeoutsEnabled = true
        } else {
            adaptiveTimeoutsEnabled = UserDefaults.standard.bool(forKey: Self.adaptiveTimeoutsEnabledKey)
        }

        simplifiedUIModeEnabled = UserDefaults.standard.bool(forKey: Self.simplifiedUIModeEnabledKey)
    }

    func isEnabled(_ type: MonitoredType) -> Bool { selectedTypeIDs.contains(type.id) }

    func toggle(_ type: MonitoredType) {
        if selectedTypeIDs.contains(type.id) { selectedTypeIDs.remove(type.id) }
        else { selectedTypeIDs.insert(type.id) }
    }

    private func persistTypes() {
        UserDefaults.standard.set(try? JSONEncoder().encode(Array(selectedTypeIDs)),
                                  forKey: Self.selectedTypeIDsKey)
    }
}
