#include <iostream>
#include <vector>
#include <memory>
#include <csignal>
#include <thread>
#include <chrono>
#include <iomanip>
#include <string>
#include <cstdlib>
#include "device_linked_list.hpp"// devicelist.cc
#include "networkInfo.hpp"
#include "mqtt_used.hpp" // 注意：这里应该是 MqttTopicsHandler.hpp
#include "mylog.hpp"
#include "nlohmann/json.hpp"
#include "taskrunner.hpp"

// --- 配置信息 ---
const std::string BROKER_ADDRESS = "tcp://119.45.167.177:1883";
const std::string USERNAME = "admin";
const std::string PASSWORD = "admin";
std::string g_client_id; 

std::atomic<bool> g_quit(false);

const std::string g_base_topic_prefix = "ser2ser/self-control"; // 用于接收动态订阅指令的主题
const std::string publish_topic_prefix = "app2dev/"; // 发布数据的主题前缀
std::string final_publish_topic;
std::string g_device_id;

std::shared_ptr<MqttTopicsHandler> g_mqtt_handler; // 改为 shared_ptr 并使用 MqttTopicsHandler 类型
NetworkInfo g_network_addr;//网络ip和mac地址获取的
DeviceList deviceTree;//设备排列和查找的
TaskRunner runner;

auto g_mqtt_send_count=0;//发送时间计数，100毫秒计数一次

// 信号处理函数，用于优雅地退出
void signalHandler(int signum) {
    mylog_info("捕获到中断信号{}",signum);
    //std::cout << "\n捕获到中断信号 (" << signum << ")，正在优雅退出..." << std::endl;
    // if (g_mqtt_handler && g_mqtt_handler->isConnected()) {
    //     std::cout << "正在断开MQTT连接..." << std::endl;
    //     g_mqtt_handler->disconnect();
        g_quit = true;
    // }
    //exit(signum);
}


// MQTT 初始化和配置函数
// **关键改动**: 此函数现在负责创建、配置并返回一个可用的 MQTT 客户端实例
std::shared_ptr<MqttTopicsHandler> mqtt_init_and_connect() {
    auto handler = std::make_shared<MqttTopicsHandler>(BROKER_ADDRESS, g_client_id);

    handler->setOnConnectionLostCallback([](const std::string& cause) {
        mylog_error("严重错误: MQTT连接已丢失！原因:{} ",cause);
        // 在这里可以添加重连逻辑或退出程序的逻辑
    });

    if (!handler->connect(USERNAME, PASSWORD)) {
        mylog_error("MQTT连接失败" );
        return nullptr; // 返回空指针表示失败
    }
    
    mylog_info("MQTT连接成功。");

   handler->AddSubscription(g_base_topic_prefix,
    [weak_handler = std::weak_ptr<MqttTopicsHandler>(handler)](const std::string& topic, const nlohmann::json& json) {
        mylog_info( "收到来自指令主题 [ {} ] 的消息。" , topic);
        try {
           if (json.value("/head/message_type"_json_pointer, 0) == 2011) {
                int result = system("sudo reboot");
                if (result != 0) {
                    std::cerr << "重启命令执行失败，错误码: " << result << std::endl;
                    // 可以添加错误处理逻辑，如日志记录或重试
                }
            }

            if (json.value("/head/message_type"_json_pointer, 0) != 6000) return;

            auto dev_id = json.at("body").at("dev_id").get<std::string>();
            auto interval_t= json.at("body").at("interval_t").get<std::string>();
            auto run_t= json.at("body").at("run_t").get<std::string>();
            auto device_status = json.at("body").at("status").get<int>();

            if(run_t.empty()||interval_t.empty()) return ;
            

            auto msg_device=  "app2dev/" + dev_id;
            mylog_info("dev_id:{}",msg_device);
            mylog_info("interval_t:{}",interval_t);
            mylog_info("run_t:{}",run_t);
            mylog_info("device_status:{}",device_status);
           //g_mqtt_handler->publish( data_topic[topic_index], transfor_json(g_positioning_data_t));
            if(device_status==1){ 
            int interval_t_num = std::stoi(interval_t);
            int run_t_num = std::stoi(run_t);
                deviceTree.addDevice(msg_device, interval_t_num, run_t_num);
            }else if(device_status==0){
                deviceTree.findDevice(msg_device);
                deviceTree.deleteDevice(msg_device);
            }
           
        }catch (const nlohmann::json::exception& e) {
            mylog_error("处理指令时JSON解析出错:",e.what());
        }
    });
   
    // g_mqtt_handler->publish(final_publish_topic, transfor_json(g_positioning_data_t));
    return handler; // 返回成功创建并配置好的客户端实例
}



auto json_send_mqtt(int message_type,int pin,int pwm_mode,int val){


    // 构造 JSON 对象
    nlohmann::json j;

    j["head"]["message_type"] = message_type;
    j["body"]["pin_setctrl"]["pin"] = pin;
    j["body"]["pin_setctrl"]["val"] = val;
    j["body"]["pwm_ctrl"]["mode"] = pwm_mode;
    j["body"]["pwm_ctrl"]["type"] = 1;
    j["body"]["pwm_ctrl"]["val"] = val;

    // 转换成字符串（默认紧凑格式，适合网络传输）
    std::string payload = j.dump();

    return payload;

}

void longRunningTask1() {
 mylog_info("[Task 1] Starting a long task...");
    
    // ... 在这里填充 myList 的数据 ...
    // 例如: myList.addDevice(...);
    const DeviceNode* traverser = deviceTree.getHead();

    while (!g_quit) {
        if (g_mqtt_send_count > 100) {
            //mylog_info("Starting to send MQTT messages for all devices...");
            
            // 每次需要遍历时，都从 myList 获取头节点
            traverser = deviceTree.getHead();
            
            while (traverser != nullptr) {
                // 在循环中，你可以访问当前节点的任何数据
                std::string currentId = traverser->deviceId;
                g_mqtt_handler->publish(currentId, json_send_mqtt(3, 26, 1, 80));
                mylog_info("已发送设备号：{}", currentId);
                
                // 移动到下一个节点
                traverser = traverser->next;
                //std::this_thread::sleep_for(std::chrono::milliseconds(100));
            }
            //mylog_info("Finished sending MQTT messages for all devices.");

            // 重要的逻辑：重置计数器，否则这个if会一直满足，导致CPU空转和消息风暴
            if(g_mqtt_send_count > 102) g_mqtt_send_count = 0; // 或者设置为一个不会立即触发下一次发送的值
        }     
        
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        g_mqtt_send_count++;
        // if(g_mqtt_send_count > 110) g_mqtt_send_count = 0; // 这行逻辑可以和上面的重置合并
    }
}

int main() {
    signal(SIGINT, signalHandler);

    spdlog::drop("my_logger");
    MyLog::init(self_device_mylog_path);

    g_client_id = g_network_addr.getip();

    
    g_mqtt_handler = mqtt_init_and_connect();
    if (!g_mqtt_handler) {
        return 1; // 如果 MQTT 连接失败，则退出
    }

    runner.addTask(longRunningTask1);

    while(!g_quit){
        std::this_thread::sleep_for(std::chrono::milliseconds(300));
    }

    return 0;
}
