import Foundation
import Security

struct AuthCredentials {
    let userId: Int
    let token: String
    let userName: String?
    let photoUrl: String?
}

actor AuthStorage {
    static let shared = AuthStorage()

    private let userIdKey = "payfrit_works_user_id"
    private let userNameKey = "payfrit_works_user_name"
    private let userPhotoKey = "payfrit_works_user_photo"
    private let serviceName = "com.payfrit.works"
    private let tokenAccount = "auth_token"

    // MARK: - Save

    func saveAuth(userId: Int, token: String, userName: String? = nil, photoUrl: String? = nil) {
        UserDefaults.standard.set(userId, forKey: userIdKey)
        if let name = userName {
            UserDefaults.standard.set(name, forKey: userNameKey)
        }
        if let photo = photoUrl, !photo.isEmpty {
            UserDefaults.standard.set(photo, forKey: userPhotoKey)
        }
        saveToKeychain(token)
    }

    // MARK: - Load

    func loadAuth() -> AuthCredentials? {
        let userId = UserDefaults.standard.integer(forKey: userIdKey)
        guard userId > 0 else { return nil }
        guard let token = loadFromKeychain(), !token.isEmpty else { return nil }
        let userName = UserDefaults.standard.string(forKey: userNameKey)
        let photoUrl = UserDefaults.standard.string(forKey: userPhotoKey)
        return AuthCredentials(userId: userId, token: token, userName: userName, photoUrl: photoUrl)
    }

    // MARK: - Clear

    func clearAuth() {
        UserDefaults.standard.removeObject(forKey: userIdKey)
        UserDefaults.standard.removeObject(forKey: userNameKey)
        UserDefaults.standard.removeObject(forKey: userPhotoKey)
        deleteFromKeychain()
    }

    // MARK: - Keychain

    private func saveToKeychain(_ token: String) {
        deleteFromKeychain()
        guard let data = token.data(using: .utf8) else { return }
        let query: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrService as String: serviceName,
            kSecAttrAccount as String: tokenAccount,
            kSecValueData as String: data,
            kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
        ]
        SecItemAdd(query as CFDictionary, nil)
    }

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

    private func deleteFromKeychain() {
        let query: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrService as String: serviceName,
            kSecAttrAccount as String: tokenAccount
        ]
        SecItemDelete(query as CFDictionary)
    }
}
