#ifndef BOX_CRTP_RSA_H
#define BOX_CRTP_RSA_H

namespace cppbox {

struct HData {
    unsigned char* data;
    size_t         len;
};

class CRSAOperatorImp;
class CRSAOperator
{
private:
    CRSAOperatorImp* imp_{};
    char*            err_{};

public:
    CRSAOperator();
    ~CRSAOperator();

    // 注意 HData 的所有内存分配与释放请统一使用:alloc_hdata 和 free_hdata
    // alloc_hdata 使用方法:设定 HData.len 后调用 alloc_hdata(HData) 即可。
public:
    /**
     * @brief 使用公钥对数据进行加密
     *
     * @param public_pem 公钥数据,应该是 PEM 格式的数据
     * @param data 要加密的数据
     * @param result 加密后的结果(自动分配内存,使用完后需要手动 free_hdata 释放)
     * @return true 表示加密成功,false 表示加密失败
     */
    bool encrypt_pub(const HData& public_pem, const HData& data, HData& result);

    /**
     * @brief 使用公钥对数据进行加密
     *
     * @param pub_path 公钥文件路径
     * @param data 要加密的数据
     * @param result 加密后的结果(自动分配内存,使用完后需要手动 free_hdata 释放)
     * @return true 表示加密成功,false 表示加密失败
     */
    bool encrypt_pub(const char* pub_path, const HData& data, HData& result);

    /**
     * @brief 使用私钥对数据进行解密
     *
     * @param private_pem 私钥数据,应该是 PEM 格式的数据
     * @param data 要解密的数据
     * @param result 解密后的结果(自动分配内存,使用完后需要手动 free_hdata 释放)
     * @return true 表示解密成功,false 表示解密失败
     */
    bool decrypt_pri(const HData& private_pem, const HData& data, HData& result);

    /**
     * @brief 使用私钥对数据进行解密
     *
     * @param pri_path 私钥文件路径
     * @param data 要解密的数据
     * @param result 解密后的结果(自动分配内存,使用完后需要手动 free_hdata 释放)
     * @return true 表示解密成功,false 表示解密失败
     */
    bool decrypt_pri(const char* pri_path, const HData& data, HData& result);

    /**
     * @brief 生成一对公钥私钥对,并存储到文件。
     *
     * @param pub_path 公钥文件存储路径
     * @param pri_path 私钥文件存储路径
     * @return true 表示生成成功,false 表示生成失败
     */
    bool generate_keypair(const char* pub_path, const char* pri_path);

    /**
     * @brief 生成一对公钥私钥对,并存储到内存。
     *
     * @param pub 公钥内存结果
     * @param pri 私钥内存结果
     * @return true 表示生成成功,false 表示生成失败
     */
    bool generate_keypair(HData& pub, HData& pri);

    /**
     * @brief 释放 HData 结构体的 data 变量堆内存
     */
    void free_hdata(HData& data);

    /**
     * @brief 为 HData 结构体的 data 变量分配内存(请先设定好 data.len)
     */
    void alloc_hdata(HData& data);

    /**
     * @brief 获取最后一次错误信息
     */
    const char* get_last_error() const;
};

}   // namespace cppbox

#endif