#include "mqtt_config.hpp"

MQTTConfig g_mqtt_config;

MQTTConfig MQTTConfig::load_from_file(const std::string &filepath)
{
    MQTTConfig cfg;

    std::ifstream ifs(filepath);
    if (!ifs)
    {
        LOG_ERROR("[Config] Failed to open config file: " + filepath);
        throw std::runtime_error("Failed to open config file: " + filepath);
    }

    nlohmann::json j;
    ifs >> j;

    cfg.device_id = j["device_id"];
    cfg.vin = j["vin"];
    cfg.server_ip = j["server_ip"];
    cfg.server_port = j["server_port"];
    cfg.client_id = j["client_id"];
    cfg.username = j["username"];
    cfg.password = j["password"];
    cfg.qos = j["qos"];
    cfg.keep_alive = j["keep_alive"];
    cfg.clean_session = j["clean_session"];

    const std::string &id = cfg.device_id;
    cfg.topics.uplink_1 = j["topics"]["uplink_1"].get<std::string>() + id;
    cfg.topics.uplink_2 = j["topics"]["uplink_2"].get<std::string>() + id;
    cfg.topics.downlink = j["topics"]["downlink"].get<std::string>() + id;

    cfg.ports.config_port = j["ports"]["config_port"];
    cfg.ports.uplink_1_port = j["ports"]["uplink_1_port"];
    cfg.ports.uplink_2_port = j["ports"]["uplink_2_port"];
    cfg.ports.downlink_port = j["ports"]["downlink_port"];

    LOG_INFO("[Config] Loaded config from " + filepath);
    LOG_INFO("  - MQTT Server: " + cfg.server_ip + ":" + std::to_string(cfg.server_port));
    LOG_INFO("  - Client ID: " + cfg.client_id);
    LOG_INFO("  - Topics: " + cfg.topics.uplink_1 + ", " + cfg.topics.uplink_2 + ", " + cfg.topics.downlink);

    return cfg;
}

bool MQTTConfig::update_mqtt_config(const ordered_json &new_values,
                                    const std::string &filepath)
{
    std::ifstream ifs(filepath);
    if (!ifs.is_open())
    {
        LOG_ERROR("[ConfigEdit] Failed to open config file: " + filepath);
        return false;
    }

    ordered_json j;
    try
    {
        ifs >> j;
        ifs.close();
    }
    catch (const std::exception &e)
    {
        LOG_ERROR(std::string("[ConfigEdit] JSON parse error: ") + e.what());
        return false;
    }

    for (auto it = new_values.begin(); it != new_values.end(); ++it)
    {
        const std::string &key = it.key();
        const auto &val = it.value();

        if (j.contains(key))
        {
            LOG_INFO("[ConfigEdit] Updating key: " + key + " -> " + val.dump());
            j[key] = val;
        }
        else
        {
            LOG_WARN("[ConfigEdit] Warning: key '" + key + "' not found in config, ignored.");
        }
    }

    std::ofstream ofs(filepath);
    if (!ofs.is_open())
    {
        LOG_ERROR("[ConfigEdit] Failed to write updated config file: " + filepath);
        return false;
    }

    ofs << j.dump(4);
    ofs.close();
    return true;
}
