import Foundation
import CryptoKit

// MARK: - Data ↔ Hex

extension Data {
    /// Convert data to lowercase hex string
    var hexString: String {
        map { String(format: "%02x", $0) }.joined()
    }

    /// Initialize Data from a hex string
    init?(hexString: String) {
        let hex = hexString.lowercased()
        guard hex.count % 2 == 0 else { return nil }
        var data = Data(capacity: hex.count / 2)
        var index = hex.startIndex
        while index < hex.endIndex {
            let nextIndex = hex.index(index, offsetBy: 2)
            guard let byte = UInt8(hex[index..<nextIndex], radix: 16) else { return nil }
            data.append(byte)
            index = nextIndex
        }
        self = data
    }

    /// Generate random bytes
    static func randomBytes(_ count: Int) -> Data {
        var data = Data(count: count)
        data.withUnsafeMutableBytes { ptr in
            _ = SecRandomCopyBytes(kSecRandomDefault, count, ptr.baseAddress!)
        }
        return data
    }
}

// MARK: - Data ↔ Base64 (Protocol Wire Format)

extension Data {
    /// Encode to standard base64 string (matching Python's base64.b64encode)
    func base64EncodedString() -> String {
        self.base64EncodedString(options: [])
    }

    /// Decode from base64 string
    static func fromBase64(_ string: String) throws -> Data {
        // Try standard base64 first, then URL-safe
        if let data = Data(base64Encoded: string, options: .ignoreUnknownCharacters) {
            return data
        }
        throw CryptoError.invalidBase64
    }
}

// MARK: - UInt32 Big-Endian

extension UInt32 {
    var bigEndianData: Data {
        var value = self.bigEndian
        return Data(bytes: &value, count: 4)
    }
}

// MARK: - CryptoKit Key → Data

extension Curve25519.KeyAgreement.PublicKey {
    var rawData: Data {
        Data(rawRepresentation)
    }
}

extension Curve25519.KeyAgreement.PrivateKey {
    var rawData: Data {
        Data(rawRepresentation)
    }
}

extension Curve25519.Signing.PublicKey {
    var rawData: Data {
        Data(rawRepresentation)
    }
}

extension Curve25519.Signing.PrivateKey {
    var rawData: Data {
        Data(rawRepresentation)
    }
}

// MARK: - String helpers

extension String {
    /// Trim whitespace and newlines
    var trimmed: String {
        trimmingCharacters(in: .whitespacesAndNewlines)
    }
}

// MARK: - Dictionary merge helper

extension Dictionary where Key == String, Value == Any {
    func string(for key: String) -> String? {
        self[key] as? String
    }

    func int(for key: String) -> Int? {
        if let i = self[key] as? Int { return i }
        if let s = self[key] as? String, let i = Int(s) { return i }
        return nil
    }

    func dict(for key: String) -> [String: Any]? {
        self[key] as? [String: Any]
    }

    func array(for key: String) -> [[String: Any]]? {
        self[key] as? [[String: Any]]
    }

    func data(for key: String) -> Data? {
        if let hex = self[key] as? String {
            return Data(hexString: hex)
        }
        return nil
    }

    func bool(for key: String) -> Bool? {
        if let b = self[key] as? Bool { return b }
        if let i = self[key] as? Int { return i != 0 }
        return nil
    }
}
