#include "mqtt_controller.hpp"
#include <iostream>
#include "mqtt_used.hpp" 
#include "mylog.hpp"

// 构造函数：启动工作线程
MqttTopicsHandler::MqttTopicsHandler(const std::string& broker_address, const std::string& client_id)
    : MqttController(broker_address, client_id) {
    worker_thread_ = std::thread(&MqttTopicsHandler::worker_thread_func, this);
}

// 析构函数：优雅地停止工作线程
MqttTopicsHandler::~MqttTopicsHandler() {
    stop_worker_ = true;
    condition_.notify_one(); // 唤醒线程，让它退出循环
    if (worker_thread_.joinable()) {
        worker_thread_.join();
    }
}

// 将任务放入队列
void MqttTopicsHandler::post_task(std::function<void()> task) {
    {
        std::lock_guard<std::mutex> lock(queue_mutex_);
        task_queue_.push(std::move(task));
    }
    condition_.notify_one(); // 唤醒工作线程来处理新任务
}

// 工作线程的主循环
void MqttTopicsHandler::worker_thread_func() {
    while (!stop_worker_) {
        std::function<void()> task;
        {
            std::unique_lock<std::mutex> lock(queue_mutex_);
            // 等待直到队列不为空或收到停止信号
            condition_.wait(lock, [this] { return !task_queue_.empty() || stop_worker_; });

            if (stop_worker_) {
                return;
            }

            task = std::move(task_queue_.front());
            task_queue_.pop();
        }
        if (task) {
            task(); // 在工作线程中执行任务
        }
    }
}


// **关键修改**：在 AddSubscription 中，如果是在回调中被调用，则将实际订阅操作 post 到工作线程
// 为了简化，我们统一将实际的订阅操作都 post 出去
void MqttTopicsHandler::AddSubscription(const std::string& topic, JsonCallback callback) {
    if (active_subscriptions_.count(topic)) {
        std::cerr << "警告：主题 \"" << topic << "\" 的订阅已存在，将被覆盖。" << std::endl;
    }

    auto wrapped_callback = [callback](const std::string& received_topic, const std::string& payload) {
        try {
            nlohmann::json j = nlohmann::json::parse(payload);
            callback(received_topic, j);
        } catch (const nlohmann::json::parse_error& e) {
            std::cerr << "在主题 \"" << received_topic << "\" 上发生JSON解析错误: " << e.what() << std::endl;
        }
    };

    active_subscriptions_[topic] = std::move(callback);

    // 将真正的 subscribe 调用封装成一个任务，交给工作线程执行
    post_task([this, topic, wrapped_callback]() {
        mylog_info("工作线程：正在执行订阅主题: {}", topic);
        // 假设 QoS 为 1
        subscribe(topic, 1, wrapped_callback);
    });
}

// 其他方法保持类似逻辑，或者如果它们不涉及阻塞调用，则无需更改
// (此处省略了其他方法的代码，它们与之前版本相同)
// ...
// ... AddSubscription(SimpleJsonCallback), AddSubscriptions, RemoveSubscription, PublishJson 的实现 ...
// ... 为了简洁，这里不再重复贴出，它们的实现无需改动，因为它们最终都调用了上面的 AddSubscription(...)
// ... 唯一需要注意的是，RemoveSubscription 内部的 Unsubscribe 也应该被 post_task
void MqttTopicsHandler::RemoveSubscription(const std::string& topic) {
    if (active_subscriptions_.erase(topic) > 0) {
        post_task([this, topic]() {
            unsubscribe(topic);
            mylog_info("工作线程：已取消订阅主题: {}",topic);
        });
    } else {
        mylog_warn("无法移除订阅：主题 {} 未被订阅。" ,topic);
    }
}

// ... InitBaseSubscription 和 PublishJson 的实现保持不变
void MqttTopicsHandler::InitBaseSubscription() {
    AddSubscription("ser/dev", [](const nlohmann::json& json) {
        try {
            mylog_info( "[收到系统状态] {}" ,json.dump(2) );
        } catch (const std::exception& e) {
            mylog_warn( "处理系统状态时出错: {}" , e.what() );
        }
    });
}

void MqttTopicsHandler::PublishJson(
    const std::string& topic,
    const nlohmann::json& json_payload,
    int qos,
    bool retained) {
    try {
        publish(topic, json_payload.dump(), qos, retained);
    } catch (const std::exception& e) {
        mylog_warn( "向主题 {} 发布 JSON 失败: {}" ,topic,e.what() );
    }
}
void MqttTopicsHandler::AddSubscription(const std::string& topic, SimpleJsonCallback callback) {
    JsonCallback full_callback = [callback](const std::string& /*topic*/, const nlohmann::json& json) {
        callback(json);
    };
    AddSubscription(topic, std::move(full_callback));
}
void MqttTopicsHandler::AddSubscriptions(const std::vector<std::string>& topics, SimpleJsonCallback common_callback) {
    for (const auto& topic : topics) {
        AddSubscription(topic, common_callback);
    }
}