import Foundation

/**
 * Centralized privacy signal store
 *
 * Manages GDPR, CCPA, and COPPA privacy signals for the SDK.
 * Reads IAB TCF/USP standard keys from UserDefaults when available,
 * and provides structured objects for bid request construction.
 */
internal class PrivacyStore {

    private let lock = NSLock()

    // SDK-set values (from public API)
    private var _gdprConsentString: String?
    private var _gdprApplies: Bool?
    private var _ccpaString: String?
    private var _coppaApplies: Bool = false

    // IAB standard UserDefaults keys
    private static let iabTcfConsentKey = "IABTCF_TCString"
    private static let iabTcfGdprAppliesKey = "IABTCF_gdprApplies"
    private static let iabUspStringKey = "IABUSPrivacy_String"

    // MARK: - Setters (called from public API)

    func setGdprConsent(_ consent: String) {
        lock.lock()
        defer { lock.unlock() }
        _gdprApplies = true
        _gdprConsentString = consent
        BCLogger.debug("PrivacyStore: GDPR consent set")
    }

    func setCcpaString(_ ccpa: String) {
        lock.lock()
        defer { lock.unlock() }
        _ccpaString = ccpa
        // Also write to IAB standard key for CMP interop
        UserDefaults.standard.set(ccpa, forKey: Self.iabUspStringKey)
        BCLogger.debug("PrivacyStore: CCPA string set")
    }

    func setCoppaApplies(_ applies: Bool) {
        lock.lock()
        defer { lock.unlock() }
        _coppaApplies = applies
        BCLogger.debug("PrivacyStore: COPPA set to \(applies)")
    }

    // MARK: - Getters

    /// Effective GDPR consent string (SDK-set takes priority, then IAB TCF)
    var gdprConsentString: String? {
        lock.lock()
        defer { lock.unlock() }
        return _gdprConsentString
            ?? UserDefaults.standard.string(forKey: Self.iabTcfConsentKey)
    }

    /// Whether GDPR applies (SDK-set takes priority, then IAB TCF)
    var gdprApplies: Bool? {
        lock.lock()
        defer { lock.unlock() }
        if let sdkValue = _gdprApplies {
            return sdkValue
        }
        let iabValue = UserDefaults.standard.object(forKey: Self.iabTcfGdprAppliesKey) as? Int
        return iabValue.map { $0 == 1 }
    }

    /// Effective CCPA/USP string (SDK-set takes priority, then IAB USP)
    var ccpaString: String? {
        lock.lock()
        defer { lock.unlock() }
        return _ccpaString
            ?? UserDefaults.standard.string(forKey: Self.iabUspStringKey)
    }

    var coppaApplies: Bool {
        lock.lock()
        defer { lock.unlock() }
        return _coppaApplies
    }

    // MARK: - Bid Request Helpers

    /// Build the `regs` object for an OpenRTB bid request
    func buildRegsDict() -> [String: Any] {
        var regs: [String: Any] = [:]
        var ext: [String: Any] = [:]

        if coppaApplies {
            regs["coppa"] = 1
        } else {
            regs["coppa"] = 0
        }

        if let gdpr = gdprApplies {
            ext["gdpr"] = gdpr ? 1 : 0
        }

        if let usp = ccpaString {
            ext["us_privacy"] = usp
        }

        if !ext.isEmpty {
            regs["ext"] = ext
        }

        return regs
    }

    /// Build the `user` object for an OpenRTB bid request
    func buildUserDict() -> [String: Any] {
        var user: [String: Any] = [:]
        var ext: [String: Any] = [:]

        if let consent = gdprConsentString {
            ext["consent"] = consent
        }

        if !ext.isEmpty {
            user["ext"] = ext
        }

        return user
    }
}
