import Foundation
import CommonCrypto

class AES {
    
    static func aes256EncryptWithData(data: Data, key: String) -> Data? {
        guard !key.isEmpty else { return nil }
        
        var keyPtr = Array<CChar>(repeating: 0, count: kCCKeySizeAES256)
        key.getCString(&keyPtr, maxLength: keyPtr.count, encoding: .utf8)
        
        let dataLength = data.count
        let bufferSize = dataLength + kCCBlockSizeAES128
        var buffer = [UInt8](repeating: 0, count: bufferSize)
        var numBytesEncrypted: size_t = 0
        
        let cryptStatus = CCCrypt(
            CCOperation(kCCEncrypt),
            CCAlgorithm(kCCAlgorithmAES),
            CCOptions(kCCOptionPKCS7Padding | kCCOptionECBMode),
            keyPtr, kCCKeySizeAES256,
            nil,
            [UInt8](data), dataLength,
            &buffer, bufferSize,
            &numBytesEncrypted
        )
        
        guard cryptStatus == kCCSuccess else { return nil }
        
        return Data(bytes: buffer, count: numBytesEncrypted)
    }

    static func aes256DecryptWithData(data: Data, key: String) -> String? {
        guard !key.isEmpty else { return nil }
        
        var keyPtr = Array<CChar>(repeating: 0, count: kCCKeySizeAES256)
        key.getCString(&keyPtr, maxLength: keyPtr.count, encoding: .utf8)
        
        let dataLength = data.count
        let bufferSize = dataLength + kCCBlockSizeAES128
        var buffer = [UInt8](repeating: 0, count: bufferSize)
        var numBytesDecrypted: size_t = 0
        
        let cryptStatus = CCCrypt(
            CCOperation(kCCDecrypt),
            CCAlgorithm(kCCAlgorithmAES),
            CCOptions(kCCOptionPKCS7Padding | kCCOptionECBMode),
            keyPtr, kCCKeySizeAES256,
            nil,
            [UInt8](data), dataLength,
            &buffer, bufferSize,
            &numBytesDecrypted
        )
        
        guard cryptStatus == kCCSuccess else { return nil }
        let decryptedData = Data(bytes: buffer, count: numBytesDecrypted)
        
        return String(data: decryptedData, encoding: .utf8)
    }
    
    static func aes256EncryptWithString(string: String, key: String) -> Data? {
        guard !key.isEmpty else { return nil }
        let data = string.data(using: .utf8)!
        return aes256EncryptWithData(data: data, key: key)
    }
    
    static func AES256Encrypt(content: String, key: String) -> String? {
        guard let resultData = aes256EncryptWithString(string: content, key: key) else { return nil }
        return resultData.base64EncodedString()
    }


    
    static func base64EncodedStringWithData(data: Data) -> String {
        return data.base64EncodedString()
    }

    static func dataWithBase64EncodedString(base64EncodedString: String) -> Data? {
        return Data(base64Encoded: base64EncodedString)
    }
    

    static func base64EncodedStringWithString(str: String) -> String {
        let data = str.data(using: .utf8)!
        return base64EncodedStringWithData(data: data)
    }

    static func stringWithBase64EncodedString(base64EncodedString: String) -> String? {
        guard let data = dataWithBase64EncodedString(base64EncodedString: base64EncodedString) else { return nil }
        return String(data: data, encoding: .utf8)
    }
    
    /// 解密 Base64 编码的加密字符串为 Data
    static func aes256DecryptBase64ToData(base64EncodedString: String, key: String) -> Data? {
        // 将 Base64 编码的字符串转换为 Data
        guard let encryptedData = vpn_Base64Decoder.dataWithBase64EncodedString(base64EncodedString)  else {
            return nil
        }
        // 解密 Data 并返回
        guard let decryptedString = aes256DecryptWithData(data: encryptedData, key: key) else {
            return nil
        }

        return decryptedString.data(using: .utf8)
    }
}
