// common.hpp
#ifndef KMS_COMMON_HPP
#define KMS_COMMON_HPP

#include <string>
#include <queue>
#include <unordered_map>
#include <openssl/crypto.h>

#define AES_BLOCK_SIZE 16

//  密钥类型
typedef enum {
    KEY_TYPE_AES,
    KEY_TYPE_ORE,
    KEY_TYPE_SAHE,
    KEY_TYPE_SMHE
} KeyType;

//  编码结构
typedef enum {
    RAW
} KeyStruct;

//  加密算法
typedef enum {
    SM4,
    AES128
} AlgorithmType;

//  CMK结构体
typedef struct {
    std::uint32_t _key_id;      //密钥id
    std::string _user_name;     //数据库用户名
    std::string _cmk_data;      //cmk数据）
    time_t _create_time;        //创建时间
    int _length;                //密钥长度
    KeyStruct _struct;          //编码结构
    AlgorithmType _alg;         //加密算法

    int _rotate_period;         //轮换周期（天数）
    bool _is_rotated;           //是否被轮转
    bool _is_primary_version;   //是否是主版本

    bool _auto_rotate;          //自动轮转状态
} CMK;

//  DEK数据库存储结构体
typedef struct {
    std::string _user_name;     //数据库用户名
    std::string _table;         //数据库表名
    std::string _column;        //数据库列名
    KeyType _type;              //密钥类型（必须有吗）
    std::string _dek_cipher;    //dek密文数据
    bool _status;               //是否启用（轮换）
    time_t _create_time;        //创建时间（必须自动轮换吗，这个可不可以只手动轮换，合同里没写要不只允许手动轮换）
    int _rotate_time;           //轮换周期（如果不是自动是不是可以没有）
    int _length;                //密钥长度（需要吗）
    KeyStruct _struct;          //编码结构（需要吗）
    AlgorithmType _alg;         //被加密算法（安全性）
} DEK;

//  DEK缓存结构体（存的东西越少越好）
typedef struct {
    std::string _user_name;     //数据库用户名
    std::string _table;         //数据库表名
    std::string _column;        //数据库列名
    KeyType _type;              //密钥类型（必须有吗）
    std::string _dek_plain;     //dek明文数据
    time_t _find_time;          //缓存创建时间
    int _cache_time;            //缓存时间
    int _length;                //密钥长度（必须有吗）
    KeyStruct _struct;          //编码结构（必须有吗）
} DEK_CACHE;

//表信息(user -> db -> table -> col?)
typedef struct {
    std::string user_name;
    std::string db_name;
    std::string table_name;
    std::queue<std::string> col_name;
    std::unordered_map<std::string, std::string> dek_store_tmp;
    std::unordered_map<std::string, std::string> dek_store_tmp_for_update;
    std::string dek_table_level_tmp;
    std::string dek_table_level_for_update;
} DbInfo;

// ============ 配置基类和具体配置类 ============
// 基础配置接口
class IKmsConfig {
public:
    virtual ~IKmsConfig() = default;
    virtual std::string getType() const = 0;
};

class LocalKmsConfig: public IKmsConfig {
public:
    const char *file_path_;
    const char *key_path_;
    const char *cmk_auto_rotate_status_path_;
    const char *user_name_;
    const char *db_name_;
    LocalKmsConfig(const char *file_path, const char *key_path, const char *cmk_auto_rotate_status_path, const char* user_name, const char* db_name)
        :file_path_(file_path),key_path_(key_path),cmk_auto_rotate_status_path_(cmk_auto_rotate_status_path),user_name_(user_name),db_name_(db_name){}
    std::string getType() const override { return "local"; }
};

// Huawei KMS 配置
class HuaweiKmsConfig : public IKmsConfig {
public:
    // 必需参数
    std::string accessKey;
    std::string secretKey;
    std::string projectId;
    std::string region;
    
    // 可选参数
    std::string endpoint = "";
    std::string keyAlias = "default-key";
    
    // 实现 getType() 方法
    std::string getType() const override {
        return "huawei";
    }
    
    // 有参构造函数
    HuaweiKmsConfig(const std::string& ak, const std::string& sk,
                   const std::string& pid, const std::string& reg,
                   const std::string& ep = "", const std::string& alias = "")
        : accessKey(ak), secretKey(sk), projectId(pid), 
          region(reg), endpoint(ep), keyAlias(alias) {}

    // 安全清除敏感信息
    void ClearSensitiveData() {
        OverwriteString(accessKey);
        OverwriteString(secretKey);
    }

private:
    void OverwriteString(std::string& str) {
        if (!str.empty()) {
            // 使用OpenSSL安全清除内存
            OPENSSL_cleanse(&str[0], str.size());
            str.clear();
        }
    }
};

#endif // KMS_COMMON_HPP