import Foundation
import Combine
import LocalAuthentication
import Security

class AppLockManager: ObservableObject {
    static let shared = AppLockManager()

    @Published var isEnabled: Bool {
        didSet { UserDefaults.standard.set(isEnabled, forKey: "appLockEnabled") }
    }
    @Published var isLocked = false
    @Published var biometricType: LABiometryType = .none

    var hasPIN: Bool { loadPIN() != nil }

    private let keychainAccount = "nahbar.applock.pin"

    private init() {
        isEnabled = UserDefaults.standard.bool(forKey: "appLockEnabled")
        refreshBiometricType()
    }

    func refreshBiometricType() {
        let ctx = LAContext()
        _ = ctx.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)
        biometricType = ctx.biometryType
    }

    // MARK: - Lock control

    func lockIfEnabled() {
        guard isEnabled, hasPIN else { return }
        isLocked = true
    }

    func unlock() {
        isLocked = false
    }

    // MARK: - PIN verification

    func verifyPIN(_ pin: String) -> Bool {
        loadPIN() == pin
    }

    func authenticateWithBiometrics(completion: @escaping (Bool) -> Void) {
        let ctx = LAContext()
        var error: NSError?
        guard ctx.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
            completion(false)
            return
        }
        ctx.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "nahbar entsperren") { success, _ in
            DispatchQueue.main.async { completion(success) }
        }
    }

    // MARK: - Keychain

    func setPIN(_ pin: String) {
        deletePIN()
        let query: [String: Any] = [
            kSecClass as String:            kSecClassGenericPassword,
            kSecAttrAccount as String:      keychainAccount,
            kSecValueData as String:        Data(pin.utf8),
            kSecAttrAccessible as String:   kSecAttrAccessibleWhenUnlockedThisDeviceOnly
        ]
        SecItemAdd(query as CFDictionary, nil)
    }

    func deletePIN() {
        SecItemDelete([
            kSecClass as String:       kSecClassGenericPassword,
            kSecAttrAccount as String: keychainAccount
        ] as CFDictionary)
    }

    private func loadPIN() -> String? {
        let query: [String: Any] = [
            kSecClass as String:       kSecClassGenericPassword,
            kSecAttrAccount as String: keychainAccount,
            kSecReturnData as String:  true,
            kSecMatchLimit as String:  kSecMatchLimitOne
        ]
        var result: AnyObject?
        guard SecItemCopyMatching(query as CFDictionary, &result) == errSecSuccess,
              let data = result as? Data else { return nil }
        return String(data: data, encoding: .utf8)
    }
}
