import Foundation
import Security

/// Shared Keychain service for passing credentials between the main app
/// and the Share Extension via App Group "group.de.hanold.bookstax".
///
/// - The main app calls `saveCredentials` whenever a profile is activated.
/// - The extension calls `loadCredentials` to authenticate API requests.
/// - Accessibility is `afterFirstUnlock` so the extension can run while the
///   device is locked after the user has unlocked it at least once.
///
/// Add this file to **both** the main app target and `BookStaxShareExtension`.
enum ShareExtensionKeychainService {

    private static let service     = "de.hanold.bookstax.shared"
    private static let account     = "activeCredentials"
    private static let accessGroup = "group.de.hanold.bookstax"

    private struct Credentials: Codable {
        let serverURL: String
        let tokenId: String
        let tokenSecret: String
    }

    // MARK: - Save (called from main app)

    /// Persists the active profile credentials in the shared keychain.
    static func saveCredentials(serverURL: String, tokenId: String, tokenSecret: String) {
        guard let data = try? JSONEncoder().encode(
            Credentials(serverURL: serverURL, tokenId: tokenId, tokenSecret: tokenSecret)
        ) else { return }

        let baseQuery: [CFString: Any] = [
            kSecClass:           kSecClassGenericPassword,
            kSecAttrService:     service,
            kSecAttrAccount:     account,
            kSecAttrAccessGroup: accessGroup
        ]

        // Try update first; add if not found.
        let updateStatus = SecItemUpdate(
            baseQuery as CFDictionary,
            [kSecValueData: data] as CFDictionary
        )
        if updateStatus == errSecItemNotFound {
            var addQuery = baseQuery
            addQuery[kSecValueData]       = data
            addQuery[kSecAttrAccessible]  = kSecAttrAccessibleAfterFirstUnlock
            SecItemAdd(addQuery as CFDictionary, nil)
        }
    }

    // MARK: - Load (called from Share Extension)

    /// Returns the stored credentials, or `nil` if the user has not yet
    /// configured the main app.
    static func loadCredentials() -> (serverURL: String, tokenId: String, tokenSecret: String)? {
        let query: [CFString: Any] = [
            kSecClass:           kSecClassGenericPassword,
            kSecAttrService:     service,
            kSecAttrAccount:     account,
            kSecAttrAccessGroup: accessGroup,
            kSecReturnData:      true,
            kSecMatchLimit:      kSecMatchLimitOne
        ]
        var result: AnyObject?
        guard SecItemCopyMatching(query as CFDictionary, &result) == errSecSuccess,
              let data = result as? Data,
              let creds = try? JSONDecoder().decode(Credentials.self, from: data)
        else { return nil }
        return (creds.serverURL, creds.tokenId, creds.tokenSecret)
    }

    // MARK: - Clear

    /// Removes the shared credentials (e.g., on logout).
    static func clearCredentials() {
        let query: [CFString: Any] = [
            kSecClass:           kSecClassGenericPassword,
            kSecAttrService:     service,
            kSecAttrAccount:     account,
            kSecAttrAccessGroup: accessGroup
        ]
        SecItemDelete(query as CFDictionary)
    }
}
