//
//  BiometricAuthManager.swift
//  Reflect
//
//  Manages Face ID / Touch ID authentication for app privacy lock.
//

import Foundation
import LocalAuthentication
import SwiftUI

@MainActor
class BiometricAuthManager: ObservableObject {

    // MARK: - Published State

    @Published var isUnlocked: Bool = true
    @Published var isAuthenticating: Bool = false

    // MARK: - App Storage

    @AppStorage(UserDefaultsStore.Keys.privacyLockEnabled.rawValue, store: GroupUserDefaults.groupDefaults)
    var isLockEnabled: Bool = false

    // MARK: - Biometric Capabilities

    var canUseBiometrics: Bool {
        let context = LAContext()
        var error: NSError?
        return context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)
    }

    var canUseDevicePasscode: Bool {
        let context = LAContext()
        var error: NSError?
        return context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error)
    }

    var biometricType: LABiometryType {
        let context = LAContext()
        var error: NSError?
        _ = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)
        return context.biometryType
    }

    var biometricName: String {
        switch biometricType {
        case .none:
            return "Passcode"
        case .faceID:
            return "Face ID"
        case .touchID:
            return "Touch ID"
        case .opticID:
            return "Optic ID"
        @unknown default:
            return "Biometrics"
        }
    }

    var biometricIcon: String {
        switch biometricType {
        case .none:
            return "lock.fill"
        case .faceID:
            return "faceid"
        case .touchID:
            return "touchid"
        case .opticID:
            return "opticid"
        @unknown default:
            return "lock.fill"
        }
    }

    // MARK: - Authentication

    func authenticate() async -> Bool {
        guard isLockEnabled else {
            isUnlocked = true
            return true
        }

        let context = LAContext()
        context.localizedCancelTitle = "Cancel"

        // Try biometrics first, fall back to device passcode
        let policy: LAPolicy = canUseBiometrics ? .deviceOwnerAuthenticationWithBiometrics : .deviceOwnerAuthentication

        isAuthenticating = true
        defer { isAuthenticating = false }

        do {
            let success = try await context.evaluatePolicy(
                policy,
                localizedReason: "Unlock Reflect to access your mood data"
            )

            isUnlocked = success
            if success {
                AnalyticsManager.shared.track(.biometricUnlockSuccess)
            }
            return success
        } catch {
            print("Authentication failed: \(error.localizedDescription)")
            AnalyticsManager.shared.track(.biometricUnlockFailed(error: error.localizedDescription))

            // If biometrics failed, try device passcode as fallback
            if canUseDevicePasscode && policy == .deviceOwnerAuthenticationWithBiometrics {
                return await authenticateWithPasscode()
            }

            return false
        }
    }

    private func authenticateWithPasscode() async -> Bool {
        let context = LAContext()

        do {
            let success = try await context.evaluatePolicy(
                .deviceOwnerAuthentication,
                localizedReason: "Unlock Reflect to access your mood data"
            )

            isUnlocked = success
            return success
        } catch {
            print("Passcode authentication failed: \(error.localizedDescription)")
            return false
        }
    }

    // MARK: - Lock Management

    func lock() {
        guard isLockEnabled else { return }
        isUnlocked = false
        AnalyticsManager.shared.track(.appLocked)
    }

    func enableLock() async -> Bool {
        // Authenticate first to enable lock - require biometrics
        let context = LAContext()
        var error: NSError?

        // Only allow enabling if biometrics are available
        guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
            print("Biometric authentication not available: \(error?.localizedDescription ?? "Unknown")")
            return false
        }

        do {
            let success = try await context.evaluatePolicy(
                .deviceOwnerAuthenticationWithBiometrics,
                localizedReason: "Verify your identity to enable app lock"
            )

            if success {
                isLockEnabled = true
                isUnlocked = true
                AnalyticsManager.shared.track(.privacyLockEnabled)
            }

            return success
        } catch {
            print("Failed to enable lock: \(error.localizedDescription)")
            return false
        }
    }

    func disableLock() {
        isLockEnabled = false
        isUnlocked = true
        AnalyticsManager.shared.track(.privacyLockDisabled)
    }
}
