#include "MqttSubscriber.h"
#include "mainwindow.h"
#include "CameraHandle.h"
#include "HttpService.h"  // 确保包含 HttpService 头文件
#include <QTimer>

MqttSubscriber* MqttSubscriber::instance = nullptr;

MqttSubscriber* MqttSubscriber::getInstance(QObject* parent) {
    if (!instance) {
        instance = new MqttSubscriber(parent);
    }
    return instance;
}

void MqttSubscriber::init(vides_data::MqttConfig &config, QString &httpUrl, QString &serialNumber) {
    // 如果客户端已存在，先断开连接再销毁
    if (client != nullptr) {
        if (MQTTAsync_isConnected(client)) {
            // 断开连接
            MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer;
            int rc = MQTTAsync_disconnect(client, &disc_opts);
            if (rc != MQTTASYNC_SUCCESS) {
                qInfo() << "客户端断开连接失败，返回编码" << rc;
            }
        }

        // 销毁现有的MQTT客户端
        MQTTAsync_destroy(&client);
        client = nullptr;  // 重置客户端指针
    }

    // 保存配置信息
    this->config = config;
    this->httpUrl = httpUrl;
    this->serialNumber = serialNumber;

    // 初始化新的MQTT客户端
    QByteArray bAddress = config.address.toUtf8();
    char* cAddress = bAddress.data();
    QByteArray bClientId = config.clientId.toUtf8();
    char* cClientId = bClientId.data();

    int rc = MQTTAsync_create(&client, cAddress, cClientId, MQTTCLIENT_PERSISTENCE_NONE, nullptr);
    if (rc != MQTTASYNC_SUCCESS) {
        qInfo() << "MQTT客户端创建失败，返回编码" << rc;
        return;
    }

    // 设置回调函数
    MQTTAsync_setCallbacks(client, this, [](void* context, char* cause) {
        static_cast<MqttSubscriber*>(context)->connectionLost(cause);
    }, [](void* context, char* topicName, int topicLen, MQTTAsync_message* m) {
        return static_cast<MqttSubscriber*>(context)->messageArrived(topicName, topicLen, m);
    }, nullptr);
}

MqttSubscriber::MqttSubscriber(QObject* parent)
    : QObject(parent), retryTimer(new QTimer(this)), client(nullptr) {

    // 连接信号和槽
    connect(this, &MqttSubscriber::connectionLostSignal, this, &MqttSubscriber::reconnectAndFetchConfig, Qt::QueuedConnection);
    retryTimer->setInterval(10000);  // 设置重试间隔为10秒
    retryTimer->setSingleShot(true);  // 单次触发
    connect(retryTimer, &QTimer::timeout, this, &MqttSubscriber::reconnectAndFetchConfig, Qt::QueuedConnection);
}

MqttSubscriber::~MqttSubscriber() {
    if (client != nullptr) {
        MQTTAsync_destroy(&client);
        client = nullptr;
    }
    instance = nullptr;
}

void MqttSubscriber::start() {
    // 确保定时器停止
    retryTimer->stop();

    // 设置连接选项
    MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
    conn_opts.keepAliveInterval = 20;
    conn_opts.cleansession = 1;

    QByteArray bUsername = config.username.toUtf8();
    char* cUsername = bUsername.data();

    QByteArray bPassword = config.password.toUtf8();
    char* cPassword = bPassword.data();

    conn_opts.username = cUsername;
    conn_opts.password = cPassword;
    conn_opts.onSuccess = [](void* context, MQTTAsync_successData* response) {
        static_cast<MqttSubscriber*>(context)->onConnect(response);
    };
    conn_opts.onFailure = [](void* context, MQTTAsync_failureData* response) {
        static_cast<MqttSubscriber*>(context)->onConnectFailure(response);
    };
    conn_opts.context = this;

    // 启动连接
    int rc;
    if ((rc = MQTTAsync_connect(client, &conn_opts)) != MQTTASYNC_SUCCESS) {
        qInfo() << "启动连接失败，返回编码" << rc;
    }
}


void MqttSubscriber::onConnect(MQTTAsync_successData* response) {
    retryTimer->stop();
    MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
    opts.onSuccess = [](void* context, MQTTAsync_successData* response) {
        static_cast<MqttSubscriber*>(context)->onSubscribe(response);
    };
    opts.onFailure = [](void* context, MQTTAsync_failureData* response) {
        static_cast<MqttSubscriber*>(context)->onSubscribeFailure(response);
    };
    opts.context = this;

    QByteArray bTopic = config.topic.toUtf8();
    char* cTopic = bTopic.data();
    int rc;
    if ((rc = MQTTAsync_subscribe(client, cTopic, config.qos, &opts)) != MQTTASYNC_SUCCESS) {
        qInfo() << "启动订阅失败，返回编码" << rc << response->token;
    }
}

void MqttSubscriber::reconnectAndFetchConfig() {
    qInfo() << "重新连接并获取配置";
    Common& instace = Common::getInstance();
    vides_data::responseConfig re_config;

    // 使用 HttpService 从远程云端拉取配置
    HttpService httpService(httpUrl);  // 替换为实际的远程URL
    vides_data::response* res = httpService.httpDeviceConfig(serialNumber, re_config);
    if (res->code == 0) {
        instace.deleteObj(res);
        re_config.mqttConfig.clientId = serialNumber;
        QString topic = QStringLiteral("/thingshub/%1/device/reply").arg(serialNumber);
        re_config.mqttConfig.topic = topic;
        this->config = re_config.mqttConfig;
        this->init(re_config.mqttConfig, httpUrl, serialNumber);
        this->start();
    } else {
        qInfo() << "配置拉取失败，等待10秒后重试";
        instace.deleteObj(res);
        QMetaObject::invokeMethod(retryTimer, "start", Qt::QueuedConnection);
    }
}

void MqttSubscriber::onConnectFailure(MQTTAsync_failureData* response) {
    qInfo() << "连接失败, rc" << (response ? response->code : -1);
    retryTimer->stop();  // 确保定时器在启动前被停止
    // 确保定时器在主线程启动
    QMetaObject::invokeMethod(retryTimer, "start", Qt::QueuedConnection);
}

void MqttSubscriber::onSubscribe(MQTTAsync_successData* response) {
    qInfo() << "订阅成功" << response->token;
}

void MqttSubscriber::onSubscribeFailure(MQTTAsync_failureData* response) {
    qInfo() << "订阅失败, rc" << (response ? response->code : -1);
}

void MqttSubscriber::connectionLost(char* cause) {
    qInfo() << "连接丢失";
    if (cause) {
        qInfo() << "Cause:" << cause;
    }
    emit connectionLostSignal();  // 发出连接丢失信号
}

int MqttSubscriber::messageArrived(char* topicName, int topicLen, MQTTAsync_message* m) {
    QString topic(topicName);
    QString payload = QString::fromUtf8(reinterpret_cast<const char*>(m->payload), m->payloadlen);

    vides_data::responseMqttData response;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(payload.toUtf8());
    if (!jsonDoc.isNull() && jsonDoc.isObject()) {
        QJsonObject jsonObj = jsonDoc.object();
        response.msg_type = jsonObj["msg_type"].toInt();
        response.sn = jsonObj["sn"].toString();
        response.uniq = jsonObj["uniq"].toString();
    } else {
        qInfo() << "Failed to parse JSON payload";
    }

    int res = -2;
    CameraHandle* cameraHandle = MainWindow::sp_this->findHandle(response.sn);
    if (cameraHandle == nullptr) {
        qInfo() << "不存在该相机";
        res = -1;
    } else {
        if (response.msg_type == 2) {
            res = cameraHandle->deviceShutdown();
        } else if (response.msg_type == 3) {
            res = cameraHandle->deviceReboot();
        } else if (response.msg_type == 4) {
            res = cameraHandle->updateSdkDevStatus(true);
        } else if (response.msg_type == 5) {
            res = cameraHandle->updateSdkDevStatus(false);
        }
    }

    vides_data::requestMqttData request;
    request.code = (res >= 0) ? 0 : 0x01;
    request.uniq = response.uniq;
    request.sn = response.sn;
    sendSubscriptionConfirmation(request);

    MQTTAsync_freeMessage(&m);
    MQTTAsync_free(topicName);
    return 1;
}

void MqttSubscriber::sendSubscriptionConfirmation(const vides_data::requestMqttData& response) {
    QString responseTopic = "/thingshub/" + response.sn + "/device/post";
    QByteArray bResponseTopic = responseTopic.toUtf8();
    char* cResponseTopic = bResponseTopic.data();
    qInfo() << "sendSubscriptionConfirmation" << cResponseTopic;

    QJsonObject json;
    json["code"] = response.code;
    json["uniq"] = response.uniq;
    QJsonDocument jsonDoc(json);
    QByteArray payload = jsonDoc.toJson(QJsonDocument::Compact);
    MQTTAsync_message pubmsg = MQTTAsync_message_initializer;

    pubmsg.payload = const_cast<char*>(payload.data());
    pubmsg.payloadlen = payload.size();
    pubmsg.qos = config.qos;
    pubmsg.retained = 0;

    MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
    opts.onSuccess = [](void* context, MQTTAsync_successData* response) {
        static_cast<MqttSubscriber*>(context)->onPublishSuccess(response);
    };
    opts.onFailure = [](void* context, MQTTAsync_failureData* response) {
        static_cast<MqttSubscriber*>(context)->onPublishFailure(response);
    };
    opts.context = this;

    int rc;
    if ((rc = MQTTAsync_sendMessage(client, cResponseTopic, &pubmsg, &opts)) != MQTTASYNC_SUCCESS) {
        qInfo() << "发送消息失败，返回编码" << rc;
    }
}

void MqttSubscriber::onPublishSuccess(MQTTAsync_successData* response) {
    qInfo() << "消息已成功发布" << response->token;
}

void MqttSubscriber::onPublishFailure(MQTTAsync_failureData* response) {
    qInfo() << "消息发布失败, rc" << (response ? response->code : -1);
}
