/**
 * @file ConfigManager.h
 * @brief 配置管理器 - 单例模式实现
 * @author BattlefieldExplorationSystem Team
 * @date 2024-01-01
 * @version 2.0
 * 
 * 线程安全的配置管理器，负责：
 * - 数据库连接配置的安全管理
 * - 系统参数的集中配置
 * - 环境变量和配置文件的统一处理
 * - 敏感信息的加密存储
 * 
 * @note 使用单例模式确保全局唯一性
 * @since 2.0
 */

#ifndef CONFIGMANAGER_H
#define CONFIGMANAGER_H

// C++标准库头文件
#include <memory>
#include <mutex>
#include <string>

// Qt头文件
#include <QObject>
#include <QSettings>
#include <QString>
#include <QVariant>

/**
 * @class ConfigManager
 * @brief 线程安全的配置管理器单例类
 * 
 * 负责管理应用程序的所有配置信息，包括：
 * - 数据库连接参数（主机、端口、用户名、密码）
 * - UI配置参数（窗口大小、样式等）
 * - 系统运行参数（日志级别、缓存设置等）
 * 
 * 特性：
 * - 线程安全的单例实现
 * - 支持配置文件和环境变量
 * - 敏感信息自动加密存储
 * - 配置变更通知机制
 * 
 * @warning 敏感配置信息不应直接硬编码，应通过环境变量或加密配置文件提供
 * @see QSettings, QCryptographicHash
 * @since 2.0
 */
class ConfigManager : public QObject
{
    Q_OBJECT

public:
    /**
     * @brief 获取配置管理器单例实例
     * @return ConfigManager& 单例引用
     * @note 线程安全的懒加载实现
     */
    static ConfigManager& getInstance();

    /**
     * @brief 析构函数
     */
    ~ConfigManager() override;

    // 禁用拷贝构造和赋值操作
    ConfigManager(const ConfigManager&) = delete;
    ConfigManager& operator=(const ConfigManager&) = delete;
    ConfigManager(ConfigManager&&) = delete;
    ConfigManager& operator=(ConfigManager&&) = delete;

    /**
     * @brief 初始化配置管理器
     * @param configFilePath 配置文件路径（可选）
     * @return bool 初始化是否成功
     */
    bool initialize(const QString& configFilePath = QString());

    // 数据库配置相关方法
    /**
     * @brief 获取数据库主机名
     * @return QString 主机名
     */
    QString getDatabaseHost() const;

    /**
     * @brief 获取数据库端口
     * @return int 端口号
     */
    int getDatabasePort() const;

    /**
     * @brief 获取数据库名称
     * @return QString 数据库名
     */
    QString getDatabaseName() const;

    /**
     * @brief 获取数据库用户名
     * @return QString 用户名
     */
    QString getDatabaseUser() const;

    /**
     * @brief 获取数据库密码
     * @return QString 密码（解密后）
     * @warning 该方法返回明文密码，仅在建立连接时使用
     */
    QString getDatabasePassword() const;

    /**
     * @brief 设置数据库配置
     * @param host 主机名
     * @param port 端口号
     * @param database 数据库名
     * @param user 用户名
     * @param password 密码（将被加密存储）
     */
    void setDatabaseConfig(const QString& host, int port, const QString& database,
                          const QString& user, const QString& password);

    // 通用配置方法
    /**
     * @brief 获取配置值
     * @tparam T 值类型
     * @param key 配置键
     * @param defaultValue 默认值
     * @return T 配置值
     */
    template<typename T>
    T getValue(const QString& key, const T& defaultValue = T{}) const
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        return m_settings->value(key, QVariant::fromValue(defaultValue)).template value<T>();
    }

    /**
     * @brief 设置配置值
     * @tparam T 值类型
     * @param key 配置键
     * @param value 配置值
     */
    template<typename T>
    void setValue(const QString& key, const T& value)
    {
        {
            std::lock_guard<std::mutex> lock(m_mutex);
            m_settings->setValue(key, QVariant::fromValue(value));
            m_settings->sync();
        }
        emit configurationChanged(key);
    }

    /**
     * @brief 检查配置键是否存在
     * @param key 配置键
     * @return bool 是否存在
     */
    bool contains(const QString& key) const;

    /**
     * @brief 移除配置项
     * @param key 配置键
     */
    void remove(const QString& key);

    /**
     * @brief 保存配置到文件
     */
    void save();

    /**
     * @brief 重新加载配置
     */
    void reload();

signals:
    /**
     * @brief 配置变更信号
     * @param key 变更的配置键
     */
    void configurationChanged(const QString& key);

private:
    /**
     * @brief 私有构造函数
     */
    explicit ConfigManager(QObject* parent = nullptr);

    /**
     * @brief 加载默认配置
     */
    void loadDefaultConfig();

    /**
     * @brief 从环境变量加载敏感配置
     */
    void loadFromEnvironment();

    /**
     * @brief 加密字符串
     * @param plainText 明文
     * @return QString 加密后的字符串
     */
    QString encryptString(const QString& plainText) const;

    /**
     * @brief 解密字符串
     * @param encryptedText 加密的字符串
     * @return QString 解密后的明文
     */
    QString decryptString(const QString& encryptedText) const;

    /**
     * @brief 生成加密密钥
     * @return QByteArray 密钥
     */
    QByteArray generateKey() const;

private:
    static std::unique_ptr<ConfigManager> m_instance;   ///< 单例实例
    static std::mutex m_instanceMutex;                  ///< 实例创建互斥锁
    
    mutable std::mutex m_mutex;                         ///< 配置访问互斥锁
    std::unique_ptr<QSettings> m_settings;              ///< Qt配置对象
    QString m_configFilePath;                           ///< 配置文件路径
    bool m_initialized;                                 ///< 初始化状态

    // 配置键常量
    static constexpr const char* KEY_DB_HOST = "database/host";
    static constexpr const char* KEY_DB_PORT = "database/port";
    static constexpr const char* KEY_DB_NAME = "database/name";
    static constexpr const char* KEY_DB_USER = "database/user";
    static constexpr const char* KEY_DB_PASSWORD = "database/password_encrypted";
};

#endif // CONFIGMANAGER_H