#include "LedMqttSubscriber.h"
#include "toml.hpp"
#include <iostream>
#include <random>
#include <chrono>
#include <sstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;

// 生成随机clientId辅助函数
std::string generateRandomClientId(const std::string &prefix = "client_")
{
    // 用时间戳+随机数生成一个简单的唯一字符串
    auto now = std::chrono::system_clock::now().time_since_epoch().count();

    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(1000, 9999);

    std::stringstream ss;
    ss << prefix << now << "_" << dis(gen);
    return ss.str();
}

MqttClient::MqttClient(const std::string &configPath)
{
    try
    {
        auto data = toml::parse(configPath);
        auto mqttConfig = toml::find(data, "mqtt");

        broker = toml::find<std::string>(mqttConfig, "host");
        clientId = generateRandomClientId();
        username = toml::find_or<std::string>(mqttConfig, "username", "");
        password = toml::find_or<std::string>(mqttConfig, "password", "");
        topic = toml::find<std::string>(mqttConfig, "topic");
        qos = toml::find_or<int>(mqttConfig, "qos", 1);

        client = new mqtt::async_client(broker, clientId);
        connOpts.set_clean_session(true);
        if (!username.empty())
            connOpts.set_user_name(username);
        if (!password.empty())
            connOpts.set_password(password);

        client->set_callback(callback);
    }
    catch (const std::exception &e)
    {
        std::cerr << "加载 MQTT 配置失败: " << e.what() << std::endl;
    }
}

MqttClient::~MqttClient()
{
    delete client;
}

bool MqttClient::start()
{
    try
    {
        client->connect(connOpts)->wait();
        client->subscribe(topic, qos)->wait();
        std::cout << "已订阅主题：" << topic << std::endl;
        return true;
    }
    catch (const mqtt::exception &e)
    {
        std::cerr << "MQTT 启动失败: " << e.what() << std::endl;
        return false;
    }
}

void MqttClient::disconnect()
{
    try
    {
        std::cout << "断开 MQTT 连接..." << std::endl;
        client->disconnect()->wait();
    }
    catch (const mqtt::exception &e)
    {
        std::cerr << "MQTT 断开失败: " << e.what() << std::endl;
    }
}

void MqttClient::Callback::message_arrived(mqtt::const_message_ptr msg)
{
    std::cout << "接收到消息: " << msg->to_string() << std::endl;

    try
    {
        auto j = json::parse(msg->to_string());

        if (j.contains("gear") && j.contains("speed"))
        {
            std::lock_guard<std::mutex> lock(parent->dataMutex);

            parent->gear = j["gear"].get<int>();
            parent->speed = j["speed"].get<double>();

            parent->lastMessageTime = std::chrono::steady_clock::now();

            std::cout << "解析 gear: " << parent->gear << ", speed: " << parent->speed << std::endl;
        }
        else
        {
            std::cerr << "消息中缺少 gear 或 speed 字段" << std::endl;
        }
    }
    catch (const std::exception &e)
    {
        std::cerr << "JSON 解析失败: " << e.what() << std::endl;
    }
}

void MqttClient::checkTimeout(std::chrono::seconds timeout)
{
    std::lock_guard<std::mutex> lock(dataMutex);
    auto now = std::chrono::steady_clock::now();
    if (now - lastMessageTime > timeout)
    {
        gear = 0;
        speed = 0.0;
        std::cout << "超时无新数据，已重置 gear 和 speed" << std::endl;
        lastMessageTime = now; // 避免重复打印
    }
}

int MqttClient::getGear()
{
    std::lock_guard<std::mutex> lock(dataMutex);
    return gear;
}

double MqttClient::getSpeed()
{
    std::lock_guard<std::mutex> lock(dataMutex);
    return speed;
}