#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);
    QJsonObject msgBodyOb;
    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();
        if(response.msg_type==6 || response.msg_type==7){
            // 解析 msg_body 字段
            if (jsonObj.contains("msg_body")) {
                QString msgBodyStr = jsonObj["msg_body"].toString();
                // 将 msg_body 字符串转换为 QJsonDocument
                QJsonDocument msgBodyDoc = QJsonDocument::fromJson(msgBodyStr.toUtf8());
                if (!msgBodyDoc.isNull() && msgBodyDoc.isObject()) {
                    msgBodyOb = msgBodyDoc.object();
                } else {
                    qInfo() << "Failed to parse msg_body as a JSON object.";
                }
            }
        }
    } else {
        qInfo() << "Failed to parse JSON payload";
    }
    //1开  2关  3 重启 4 GB28181开 5 GB28181 关 6 一键配网 7 WIFI配留 8 复位GB28181
    int res = -2;
    CameraHandle* cameraHandle = MainWindow::sp_this->findHandle(response.sn);
    int hDevice=0;
    if (cameraHandle == nullptr ) {
        if(response.msg_type == 6){
            hDevice=-1;
        }else {
            qInfo() << "不存在该相机";
            res = -1;
        }
    } else {
        switch (response.msg_type) {
        case 2: res = cameraHandle->deviceShutdown(); break;
        case 3: res = cameraHandle->deviceReboot(); break;
        case 4: res = cameraHandle->updateSdkDevStatus(true); break;
        case 5: res = cameraHandle->updateSdkDevStatus(false); break;
        case 6: hDevice = cameraHandle->getHdevice(); break;
        case 7: {
            if (msgBodyOb.contains("username") && msgBodyOb.contains("password")) {
                QString username = msgBodyOb["username"].toString();
                QString password = msgBodyOb["password"].toString();
                res = (cameraHandle->sdkWifi(password, username) ? 0x01 :-1);
            } else {
                qInfo() << "IP username not found in msg_body.";
                qInfo() << "IP password not found in msg_body.";
            }
            break;
        }
        case 8: res = cameraHandle->resetGb28181(); break;
        default: qInfo() << "Unknown message type"; break;
        }
    }

    if (response.msg_type == 6) {
        NonConnectedCameraHandle *connectedCameraHandle =NonConnectedCameraHandle::getInstance();
        QString ipAddress ;
        // 提取 ip 地址
        if (msgBodyOb.contains("ip") && msgBodyOb["ip"].isString()) {
            ipAddress = msgBodyOb["ip"].toString();
            qInfo() << "IP Address: " << ipAddress;
        } else {
            qInfo() << "IP address not found in msg_body.";
        }

        res=connectedCameraHandle->distributionNetwork(ipAddress,response.sn,hDevice);
    }

    vides_data::requestMqttData request;
    request.code = (res >= 0) ? 0 : 0x01;
    request.msg =  (res >= 0) ?"成功":"失败";
    request.uniq= response.uniq;
    sendSubscriptionConfirmation(request,response.sn);

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

void MqttSubscriber::sendSubscriptionConfirmation(const vides_data::requestMqttData& response,QString &sn) {
    QString responseTopic = "/thingshub/" +response.uniq+ "/device/post";
    QByteArray bResponseTopic = responseTopic.toUtf8();
    char* cResponseTopic = bResponseTopic.data();
    qInfo()<<QString("SN(%1): sendSubscriptionConfirmation->cResponseTopic%2").arg(sn).arg(cResponseTopic);
    
    // response.sn
    QJsonObject json;
    json["code"] = response.code;
    json["msg"] = response.msg;
    
    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);
}
