#ifndef IKMS_CORE_HPP
#define IKMS_CORE_HPP

#include "kms_common.hpp"
#include <iostream>
#include "json.hpp"
using json = nlohmann::json;

class IKmsCore {
public:
    virtual ~IKmsCore() = default;

    /**
     * @brief 自定义初始化逻辑，不需要手动调用，会在单例第一次被创建时自动调用
     * local：解析json, 随后LoadCmkByUsername
     * tencent：或许可以是从配置文件中读取参数
     */
    virtual bool init() = 0;

    /* ------------------------------------CMK 管理-----------------------------------------------*/


    /** 
     * @brief 查询用户是否有cmk
     * @param user_name 输入：用户名
     * @return bool 返回 true 表示存在，false 表示不存在
     */
    virtual bool hasCmk(const std::string &user_name) const = 0;
    
    /**
     * @brief 创建新的客户主密钥（CMK）
     * @param user_name 输入：用户名，用于关联 CMK
     * @param rotate_period 输入：CMK 轮换周期（天数）
     * @param new_cmk 输出：创建的 CMK 结构体，包含密钥 ID、数据等信息
     * @param ks 输入：密钥编码结构，默认为 RAW
     * @param alg 输入：加密算法，默认为 AES128
     * @return bool 返回 true 表示创建成功，false 表示失败
     */
    virtual bool createCmk(const std::string& user_name, int rotate_period,
                           KeyStruct ks = KeyStruct::RAW, AlgorithmType alg = AlgorithmType::AES128) = 0;
    
    /**
     * @brief 删除指定用户的 CMK
     * @param user_name 输入：要删除 CMK 的用户名
     * @return bool 返回 true 表示删除成功，false 表示失败
     */
    virtual bool deleteCmk(const std::string& user_name) = 0;

    virtual bool describeCmk(const std::string &user_name, std::string &result, bool decrypt) = 0;
    
    /* ------------------------------------ 轮转 -----------------------------------------------*/
    /**
     * 非纯虚函数, 可以不实现
     */

    /**
     * @brief 立即轮换指定用户的 CMK 
     * @param user_name 输入：要轮换 CMK 的用户名
     * @return bool 返回 true 表示轮换成功，false 表示失败
     */
    virtual bool rotateCmkNow(const std::string& user_name){
        std::cout << "not implement" << std::endl;
    }
    /**
     * @brief 启用或者关闭自动轮转
     * @param auto_rotate_action 输入/输出：轮换命令（如启动或停止自动轮换），可能为 nullptr
     * @param user_name 输入：用户名
     * @return bool 返回 true 表示命令处理成功，false 表示失败
     */
    virtual bool handleAutoRotateCmd(std::string* auto_rotate_action, const std::string& user_name){
        std::cout << "not implement" << std::endl;
    }

    /**
     * @brief 获取指定用户的 CMK 自动轮换状态
     * @param user_name 输入：用户名
     * @return bool 返回 true 表示自动轮换启用，false 表示未启用或用户不存在
     */
    virtual bool getCmkAutoRotateStatusByUsername(const std::string& user_name){
        std::cout << "not implement" << std::endl;
    }


    /* ------------------------------------ 加密解密 -----------------------------------------------*/
    /**
     * 这里是使用哪个CMK的问题
     * 在Local中, 我通过在 initialize 的时候设置好 _user_name 成员, 随后通过 init -> LoadCmkByUsername 保存在 KMS的 _cmk 变量中 中
     * 此后的加密(认为一个pgConn不会切换用户, 始终使用同一个cmk, 如果轮换在轮换结尾设置新的 _cmk )
     * TencentKMS 应该无法这样做(无法缓存在本地), 只能保存 _user_name 然后每次加解密都选用 _user_name 对应的 cmk
     */


    /**
     * @brief 使用 CMK 加密 DEK
     * @param dek 输入/输出：要加密的 DEK 数据，加密后存储在原变量
     * @return bool 返回 true 表示加密成功，false 表示失败
     */
    virtual bool encryptData(std::string& dek) = 0;

    /**
     * @brief 使用 CMK 解密 DEK 
     * @param dek 输入/输出：要解密的 DEK 密文，解密后存储在原变量
     * @return bool 返回 true 表示解密成功，false 表示失败
     */
    virtual bool decryptData(std::string& dek) = 0;

    /* ------------------------------------新建DEK -------------------------------------------------*/
    /**
     * @brief 通过列名与CMK 派生出 col_dek, 表级 列密钥使用 "" 空字符串派生
     */
    virtual bool createDek(std::string &col_dek, const std::string &column_name) = 0;
};

#endif