//
/*
 * Copyright (c) 2025 BWI GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import Security
import Foundation

enum SharedKeychainConfig {
    static var sharedGroup: String {
        Bundle.main.object(forInfoDictionaryKey: "KeychainMigrationSharedGroup") as? String
        ?? ""
    }
    
    static var service = "de.bwi.sharedkeychain"
}

// bwi #7565 do some keychain magic, needs to have entitlement for SharedKeychainConfig.sharedGroup and needs to store it in info.plist to hide team id.

enum SharedKeychain {
    @discardableResult
    static func save(
        account: String,
        value: String
    ) -> OSStatus {
        let data = value.data(using: .utf8)!

        // Delete existing item first
        SharedKeychain.delete(account: account)

        // Add new value
        let addQuery: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrAccount as String: account,
            kSecAttrService as String: SharedKeychainConfig.service,
            kSecAttrAccessGroup as String: SharedKeychainConfig.sharedGroup,
            kSecValueData as String: data
        ]
        return SecItemAdd(addQuery as CFDictionary, nil)
    }

    static func load(
        account: String
    ) -> String? {
        let query: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrAccount as String: account,
            kSecAttrService as String: SharedKeychainConfig.service,
            kSecAttrAccessGroup as String: SharedKeychainConfig.sharedGroup,
            kSecMatchLimit as String: kSecMatchLimitOne,
            kSecReturnData as String: true
        ]

        var result: AnyObject?
        let status = SecItemCopyMatching(query as CFDictionary, &result)

        guard status == errSecSuccess,
              let data = result as? Data,
              let value = String(data: data, encoding: .utf8) else {
            return nil
        }
        return value
    }

    @discardableResult
    static func delete(
        account: String
    ) -> OSStatus {
        let query: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrAccount as String: account,
            kSecAttrService as String: SharedKeychainConfig.service,
            kSecAttrAccessGroup as String: SharedKeychainConfig.sharedGroup
        ]
        return SecItemDelete(query as CFDictionary)
    }
}
