#include <iostream>
#include <vector>
#include <memory>
#include <csignal>
#include <thread>
#include <chrono>
#include <iomanip>
#include <string>
#include <cstdlib>
#include "device_tag_bind.hpp"
#include "serial_port.hpp"
#include "positioning_data.hpp"
#include "mqtt_used.hpp" // 注意：这里应该是 MqttTopicsHandler.hpp
#include "file_operations.hpp"

// --- 配置信息 ---
const std::string BROKER_ADDRESS = "tcp://119.45.167.177:1883";
const std::string CLIENT_ID = "cpp_client_6456456"; // 客户端ID必须唯一
const std::string USERNAME = "admin";
const std::string PASSWORD = "admin";

// 主题定义
const std::string g_base_topic_prefix = "ser2dev/"; // 用于接收动态订阅指令的主题
const std::string publish_topic_prefix = "positioning/"; // 发布数据的主题前缀
std::string final_publish_topic;
std::string g_device_id;

positioningMapData g_positioning_data_t;

// --- 全局变量 ---
// 使用智能指针管理串口和MQTT客户端的生命周期
std::unique_ptr<SerialPort> g_serial_port;
std::shared_ptr<MqttTopicsHandler> g_mqtt_handler; // 改为 shared_ptr 并使用 MqttTopicsHandler 类型
std::shared_ptr<FileReader> g_file_read; 

deviceTable g_device_tag_t;
// 串口数据相关的全局变量
std::vector<uint16_t> x_local(21);
std::vector<uint16_t> y_local(21);
std::vector<int> tag_id;

// 预设指令
const std::vector<uint8_t> cmd_continuous = {0x01, 0x10, 0x00, 0x3B, 0x00, 0x01, 0x02, 0x00, 0x04, 0xA3, 0x18};
const std::vector<uint8_t> cmd_stop_modbus = {0x01, 0x10, 0x00, 0x3B, 0x00, 0x01, 0x02, 0x00, 0x00, 0xA2, 0xDB};

// 信号处理函数，用于优雅地退出
void signalHandler(int signum) {
    std::cout << "\n捕获到中断信号 (" << signum << ")，正在优雅退出..." << std::endl;
    if (g_serial_port && g_serial_port->isOpen()) {
        std::cout << "正在发送停止指令并关闭串口..." << std::endl;
        g_serial_port->send(cmd_stop_modbus);
        g_serial_port->close();
    }
    if (g_mqtt_handler && g_mqtt_handler->isConnected()) {
        std::cout << "正在断开MQTT连接..." << std::endl;
        g_mqtt_handler->disconnect();
    }
    exit(signum);
}

// 串口消息处理回调函数
void onSerialMessageReceived(const std::vector<uint8_t>& message) {
    if (message.size() < 17) { // 基本长度检查
        return;
    }

    // 直接从 message vector 访问数据，无需拷贝
    if (message[10] == 0x01) {
        int i = static_cast<int>(message[8]);
        if (i>0 && static_cast<size_t>(i) < x_local.size()) {
            x_local[i] = (static_cast<uint16_t>(message[13]) << 8) | message[14];
            y_local[i] = (static_cast<uint16_t>(message[15]) << 8) | message[16];
            
            static auto last_print = std::chrono::steady_clock::now();
            if ((std::chrono::steady_clock::now() - last_print) > std::chrono::milliseconds(200)) {
                std::cout << "串口数据更新 -> 标签ID: " << tag_id[i]
                      << ", X: " << x_local[i]
                      << ", Y: " << y_local[i] << std::endl;
                last_print = std::chrono::steady_clock::now();
            }
            
        }
    }
   // std::this_thread::sleep_for(std::chrono::milliseconds(200));
}

std::string file_open_read(){
    
    g_file_read->open();

    return g_device_id=g_file_read->readAll();

}

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

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

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

    std::string g_base_topic = g_base_topic_prefix + g_device_id;

    // 构造发布主题，例如：positioning/CN040300000002
    final_publish_topic = publish_topic_prefix + g_device_id; 

   handler->AddSubscription(g_base_topic,
    [weak_handler = std::weak_ptr<MqttTopicsHandler>(handler)](const std::string& topic, const nlohmann::json& json) {
        std::cout << "收到来自指令主题 [" << topic << "] 的消息。" << std::endl;
        try {
            if (json.value("/head/message_type"_json_pointer, 0) != 5000) return;

            auto dev_id = json.at("body").at("dev_id").get<std::string>();
            auto tag_id = json.at("body").at("id").get<std::string>();
            auto data_topic = "app2dev/" + dev_id;
            g_device_tag_t.set(tag_id, data_topic);

            // 转换为整数
            int tag_id_num_int = std::stoi(tag_id);  // 可能抛出 std::invalid_argument 或 std::out_of_range
            positioningMapData bind_tag_send_data_t = {
                .id = tag_id_num_int,
                .resWidth = 500,
                .resHeight = 500,
                .resX = x_local[tag_id_num_int],
                .resY = y_local[tag_id_num_int],
                .resZ = 0
            };
            g_positioning_data_t=bind_tag_send_data_t;
            g_mqtt_handler->publish(final_publish_topic, transfor_json(g_positioning_data_t));

            if (auto shared_handler = weak_handler.lock()) {
                std::cout << "指令解析成功，准备动态订阅主题: " << data_topic << std::endl;
                // 调用 AddSubscription，它现在会将订阅任务 post 到工作线程，避免死锁
                shared_handler->AddSubscription(data_topic,
                    [](const std::string& sub_topic, const nlohmann::json& sub_json) {
                        if (sub_json.contains("head") && 
                            sub_json["head"].is_object() &&
                            sub_json["head"].contains("message_type") &&
                            sub_json["head"]["message_type"].is_number_integer() &&
                            sub_json["head"]["message_type"].get<int>() == 2011){
                                system("sudo reboot");
                            }
                            else if (sub_json.contains("head") && 
                                sub_json["head"].is_object() &&
                                sub_json["head"].contains("message_type") &&
                                sub_json["head"]["message_type"].is_number_integer() &&
                                sub_json["head"]["message_type"].get<int>() == 3){
                                    
                        std::string device_local_label_id=g_device_tag_t.find(sub_topic);
                        int tag_id_num_int = std::stoi(device_local_label_id);
                        if(device_local_label_id!="empty"){
                               positioningMapData bind_tag_send_data_t = {
                                .id = tag_id_num_int,
                                .resWidth = 500,
                                .resHeight = 500,
                                .resX = x_local[tag_id_num_int],
                                .resY = y_local[tag_id_num_int],
                                .resZ = 0
                                };
                                g_positioning_data_t=bind_tag_send_data_t;
                                std::cout<<"发送成功"<<std::endl;
                            g_mqtt_handler->publish(final_publish_topic, transfor_json(g_positioning_data_t));
                                //使用全局的 g_mqtt_handler 来发布
                            //mqtt_handler->PublishJson(final_publish_topic, root_json);
                            }
                        }
                    });
            }
        } catch (const nlohmann::json::exception& e) {
            std::cerr << "处理指令时JSON解析出错: " << e.what() << std::endl;
        }
    });

    return handler; // 返回成功创建并配置好的客户端实例
}



int main(int argc, char* argv[]) {
    // 注册信号处理
    //signal(SIGTERM, signalHandler); 
    signal(SIGINT, signalHandler);
    
    // 初始化 tag_id
    for (int i = 0; i <= 20; ++i) {
        tag_id.push_back(i);
    }

    g_file_read = std::make_shared<FileReader>(DEVICE_FILE_PATH);

    g_device_id = file_open_read();

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

    // --- 2. 初始化串口 ---
    std::string port = "/dev/ttyUSB0";
    if (argc > 1) {
        port = argv[1];
    }
    g_serial_port = std::make_unique<SerialPort>(port);
    if (!g_serial_port->open()) {
        return 1;
    }
    
    // 启动串口监听线程
    g_serial_port->startListening(onSerialMessageReceived);
    std::cout << "串口监听线程已启动。" << std::endl;

    // 发送开始连续读取的指令
    g_serial_port->send(cmd_continuous);
    std::cout << "已发送连续读取指令到串口设备。" << std::endl;
    while(1){
         std::this_thread::sleep_for(std::chrono::milliseconds(300));
    }
    

    return 0; // 正常情况下不会执行到这里
}