#include "TcpServerThread.h"

#include <QHostAddress>
#include <QDateTime>
#include <QDebug>
#include <QThread>
#include <QEventLoop>

#include "DataTypeDef.h"
#include "ConfigManager.h"
#include "LoggerHelper.h"
#include "GeneralInterface.h"
#include "Globals.h"

TcpServerThread* tcpThread = nullptr;
TcpServerThread *TcpServerThread::instance()
{
    static QMutex mutex;
    if (!tcpThread) {
        QMutexLocker locker(&mutex);
        if (!tcpThread) {
            tcpThread = new TcpServerThread();
        }
    }
    return tcpThread;
}

TcpServerThread::TcpServerThread(QObject *parent)
    : QObject(parent)
    , m_server(nullptr)
    , m_client(nullptr)
    , m_workerThread(nullptr)
    , m_eventLoop(nullptr)
    , m_isConnected(false)
    , m_trans_id(0)
{
    // 注册SocketError类型
    qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");

    m_tcu_cfg = ConfigManager::instance()->tcu_cfg();
    initErrorDescriptions();
    initTypeDescriptions();

    connect(GLOBALS, &Globals::tcuConfigValueChanged, this, [this](const TCU_CFG& tcu_cfg){
        m_tcu_cfg = tcu_cfg;
    });

    // 创建工作线程
    startWorkerThread();
}

TcpServerThread::~TcpServerThread()
{
    stopServer();
    stopWorkerThread();
}

void TcpServerThread::startWorkerThread()
{
    if (!m_workerThread) {
        m_workerThread = new QThread();
        m_eventLoop = new QEventLoop();

        // 创建工作线程中的对象
        m_server = new QTcpServer();
        m_server->moveToThread(m_workerThread);

        // 连接服务器信号
        connect(m_server, &QTcpServer::newConnection, this, &TcpServerThread::handleNewConnection);

        // 创建心跳定时器
        auto gun_num = ConfigManager::instance()->ccu_cfg().GUN_Numb;
        for (int index = 1; index <= gun_num; index++) {
            QTimer* timer = new QTimer();
            timer->moveToThread(m_workerThread);
            m_heartbeatTimer.insert(index, timer);

            connect(timer, &QTimer::timeout, this, [this, index]() {
                emit heartbeatTimeout(index);
                if (!m_dataReceived.values().contains(true)) {
                    LOG_WARNING(QString("No data received for gun %1 within timeout period").arg(index));
                    removeClient();
                } else {
                    // 重置数据接收状态
                    m_dataReceived[index] = false;
                }
            });
        }

        // 启动工作线程
        m_workerThread->start();
    }
}

void TcpServerThread::stopWorkerThread()
{
    if (m_workerThread) {
        // 停止所有定时器
        for (auto timer : m_heartbeatTimer) {
            if (timer->isActive()) {
                QMetaObject::invokeMethod(timer, "stop", Qt::BlockingQueuedConnection);
            }
            QMetaObject::invokeMethod(timer, "deleteLater", Qt::QueuedConnection);
            timer = nullptr;
        }
        m_heartbeatTimer.clear();

        // 停止服务器
        if (m_server) {
            QMetaObject::invokeMethod(m_server, "close", Qt::BlockingQueuedConnection);
            QMetaObject::invokeMethod(m_server, "deleteLater", Qt::QueuedConnection);
            m_server = nullptr;
        }

        // 停止工作线程
        m_workerThread->quit();
        m_workerThread->wait();
        delete m_workerThread;
        m_workerThread = nullptr;
    }

    if (m_eventLoop) {
        delete m_eventLoop;
        m_eventLoop = nullptr;
    }
}

int TcpServerThread::init()
{
    if (!m_server) {
        return TcpError::INIT_FAILED;
    }

    if (m_server->isListening()) {
        return INIT_OK;
    }

    bool success = false;
    QMetaObject::invokeMethod(m_server, [this, &success]() {
        success = m_server->listen(QHostAddress::Any, m_tcu_cfg.tcp_server_cfg.port);
    }, Qt::BlockingQueuedConnection);

    if (!success) {
        LOG_ERROR("Tcp server could not start: " + m_server->errorString());
        emit errorOccurred(TcpError::INIT_FAILED, "Failed to start TCP server: " + m_server->errorString());
        return TcpError::INIT_FAILED;
    }

    LOG_INFO("Tcp server started on port: " + QString::number(m_tcu_cfg.tcp_server_cfg.port));
    return TcpError::SUCCESS;
}

/**
 * @brief TcpServerThread::stopServer   关闭服务器
 */
void TcpServerThread::stopServer()
{
    if (m_server->isListening()) {
        m_server->close();
    }

    removeClient();
}

/**
 * @brief TcpServerThread::sendData 发送数据
 * @param cmd       命令
 * @param data      数据
 * @param trans_id  事务ID
 * @return
 */
bool TcpServerThread::sendData(const uint8_t cmd, const QByteArray &data, const uint16_t &trans_id)
{
    if (!m_client || m_client->state() != QAbstractSocket::ConnectedState) {
        emit errorOccurred(TcpError::INVALID_SOCKET, "No connected client");
        return false;
    }

    MSG_HEAD msg_head;
    msg_head.trans_id   = trans_id;
    msg_head.proto_id   = 0x0000;
    msg_head.length     = data.size();
    msg_head.unit_id    = 0x01;
    msg_head.cmd        = cmd;

    QByteArray sendData;
    sendData.append(GeneralInterface::networkStructToByteArray(msg_head));
    sendData.append(data);

    int retryCount = 0;
    while (retryCount < MAX_RETRY_COUNT) {
        m_client->write(sendData);

        qDebug() << QString("TCP send data: " + sendData.toHex(' ').toUpper());
        if (m_client->waitForBytesWritten(DEFAULT_TIMEOUT)) {
            return true;
        }

        retryCount++;
        if (retryCount < MAX_RETRY_COUNT) {
            LOG_WARNING(QString("Retry sending data: %1/%2").arg(retryCount).arg(MAX_RETRY_COUNT));
            QThread::msleep(100);
        }
    }

    emit errorOccurred(TcpError::SEND_FAILED, "Failed to send data after retries");
    return false;
}

/**
 * @brief TcpServerThread::sendAndWaitForReply  发送数据并等待回复
 * @param cmd       命令
 * @param data      数据
 * @param gun_id    枪号
 * @param timeout   超时时间
 * @return
 */
bool TcpServerThread::sendAndWaitForReply(const uint8_t cmd, const QByteArray &data, int gun_id, const int &timeout)
{
    if (!m_client || m_client->state() != QAbstractSocket::ConnectedState) {
        emit errorOccurred(TcpError::INVALID_SOCKET, "No connected client");
        return false;
    }

    QEventLoop loop;
    QTimer timer;
    bool replyReceived = false;
    int replyResult = -1;

    // 连接信号槽，收到回复时退出事件循环
    QMetaObject::invokeMethod(this, [this, &gun_id, &replyReceived, &replyResult, &loop]() {
        connect(this, &TcpServerThread::authResult, this, [&gun_id, &replyReceived, &replyResult, &loop](int recv_gun_id, int result) {
            if (recv_gun_id == gun_id) {
                replyReceived = true;
                replyResult = result;
                loop.quit();
            }
        });
    });

    // 超时处理
    timer.setSingleShot(true);
    connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);

    // 发送指令
    sendData(cmd, data);

    // 启动计时器并进入事件循环
    timer.start(timeout);
    loop.exec();

    if (!replyReceived) {
        LOG_WARNING(QString("Authentication timeout, gun number:%1, instruction:0x%2").arg(gun_id).arg(cmd, 0, 16));
        emit authResult(gun_id, AuthError::TIMEOUT);
        return false;
    }

    LOG_INFO(QString("cmd exec successfully, gun number:%1, instruction:0x%2").arg(gun_id).arg(cmd, 0, 16));
    // 正常收到回复
    emit authResult(gun_id, AuthError::SUCCESS);
    return true;
}

/**
 * @brief TcpServerThread::isClientConnected    判断客户端是否连接
 * @return  true/false
 */
bool TcpServerThread::isClientConnected() const
{
    return m_isConnected;
}

/**
 * @brief TcpServerThread::chargeGunAuth    枪号认证
 * @param gun_id    枪号
 * @param cardId    卡号
 * @return  true/false
 */
bool TcpServerThread::chargeGunAuth(const uint32_t &gun_id, const QString &cardId)
{
    GUN_AUTH info;
    info.GUNID = gun_id;
    memset(info.EMID, 0, 32);
    memcpy(info.EMID, cardId.toUtf8().data(), cardId.size());
    info.requestKWs = 0;

    // qDebug() << "send card Id auth" << cardId;
    auto data = GeneralInterface::encodeAuthInfo(info);

    return sendAndWaitForReply(CHARGE_GUN_AUTH_CMD, data, gun_id);
}

/**
 * @brief TcpServerThread::chargeGunQr  枪号认证
 * @param gun_id    枪号
 * @param qr        二维码
 * @return          true/false
 */
bool TcpServerThread::chargeGunQr(const uint32_t &gun_id, const QString &qr)
{
    GUN_AUTH info;
    info.GUNID = gun_id;
    memset(info.EMID, 0, 32);
    memcpy(info.EMID, qr.toUtf8().data(), qr.size());
    info.requestKWs = 0;

    auto data = GeneralInterface::encodeAuthInfo(info);

    return sendAndWaitForReply(CHARGE_GUN_QR_CMD, data, gun_id);
}

/**
 * @brief TcpServerThread::slotChargingCtl  充电控制
 * @param data   充电控制数据
 */
void TcpServerThread::slotChargingCtl(charging_control_info_t &data)
{
    switch (data.cmd) {
    case CHARGE_GUN_START_CMD: {
        START_CHARGE_CMD ctl_data;
        ctl_data.GUNID = data.gunID;
        memcpy(ctl_data.EMID, data.cardID.toUtf8().data(), data.cardID.size());
        if (data.requestPowerByMinutes) ctl_data.requestMinutes = data.minutes;
        else if (data.requestPowerByPowerKW) ctl_data.requestKWs = data.powerKW;
        else if (data.requestPowerBySoc) ctl_data.requestSOC = data.soc;
        ctl_data.authorizationResult = 0;
        if (sendAndWaitForReply(data.cmd, GeneralInterface::encodeStartChargeGunInfo(ctl_data), data.gunID)) {
            LoggerHelper::instance()->warning(QString("GUN%1 : Start Charge Faild...").arg(data.gunID));
            return;
        }
        break;
    }
    case CHARGE_GUN_STOP_CMD: {
        STOP_CHARGE_CMD ctl_data;
        ctl_data.GUNID = data.gunID;
        memcpy(ctl_data.EMID, data.cardID.toUtf8().data(), data.cardID.size());
        ctl_data.authorizated = 0;
        if (sendAndWaitForReply(data.cmd, GeneralInterface::encodeStopChargeGunInfo(ctl_data), data.gunID)) {
            LoggerHelper::instance()->warning(QString("GUN%1 : Start Charge Faild...").arg(data.gunID));
            return;
        }
        break;
    }
    default:
        break;
    }
}

/**
 * @brief TcpServerThread::parseClientMsg    解析客户端消息
 * @param data   消息数据
 */
void TcpServerThread::parseClientMsg(const QByteArray &data)
{
    if (data.size() < MESSAGE_HEAD_LENGTH) {
        emit errorOccurred(TcpError::INVALID_SOCKET, "Invalid message format");
        return;
    }

    // 处理报文帧头
    MSG_HEAD msg_head;
    msg_head.trans_id   = GeneralInterface::toUInt16(data.mid(0, 2));
    msg_head.proto_id   = GeneralInterface::toUInt16(data.mid(2, 2));
    msg_head.length     = GeneralInterface::toUInt16(data.mid(4, 2));
    msg_head.unit_id    = GeneralInterface::toUInt8(data.mid(6, 1));
    msg_head.cmd        = GeneralInterface::toUInt8(data.mid(7, 1));

    m_trans_id = msg_head.trans_id;

    // 截取报文中的数据部分
    auto info = data.mid(MESSAGE_HEAD_LENGTH);

    // 验证数据长度
    if (msg_head.length != info.size()) {
        emit errorOccurred(TcpError::INVALID_SOCKET, "Invalid message length");
        return;
    }

    m_isAuthReply = false;
    qDebug() << QString("TCP recv data: " + data.toHex(' ').toUpper());
    // 处理不同类型的消息
    switch (msg_head.cmd) {
    case CHARGE_GUN_BASIC_INFO_CMD:
        parseChargeGunBasicInfo(info);
        break;
    case CHARGE_GUN_CHARGE_INFO_CMD:
        parseChargeGunChargeInfo(info);
        break;
    case CHARGE_GUN_START_CMD:
        parseChargeGunStart(info);
        break;
    case CHARGE_GUN_STOP_CMD:
        parseChargeGunStop(info);
        break;
    case HEARTBEAT_REPLY_CMD:
        parseHeartbeatReply(info);
        break;
    case CHARGE_GUN_AUTH_CMD:
    case CHARGE_GUN_QR_CMD:
        parseAuthResult(info);
        m_isAuthReply = true;
        break;
    default:
        emit errorOccurred(TcpError::INVALID_SOCKET, "Unknown command: " + QString::number(msg_head.cmd));
        break;
    }
}

/**
 * @brief TcpServerThread::parseChargeGunBasicInfo  解析充电枪基本信息
 * @param data   充电枪基本信息数据
 */
void TcpServerThread::parseChargeGunBasicInfo(const QByteArray &data)
{
    charge_gun_basic_info_t basic_info = GeneralInterface::decodeChargeBasicInfo(data);

    // 解析消息头以获取充电枪ID
    m_dataReceived[basic_info.GUNID] = true;

    // qDebug() << QString("Gun id: %1").arg(QString::number(basic_info.GUNID, 16));

    QStringList error_str_list  = QStringList();
    QStringList state_str_list  = QStringList();
    QStringList type_str_list   = QStringList();
    // 处理充电枪错误码信息
    parseGunError(basic_info.GUN_Error, basic_info.GUNID);

    // 处理充电枪状态信息
    parseGunState(basic_info.GUN_State, basic_info.GUNID);

    // 处理充电枪类型信息
    parseGunType(basic_info.GUN_Type, basic_info.GUNID);

    sendHeatReply(CHARGE_GUN_BASIC_INFO_CMD, basic_info.GUNID);

    refreshBasicInfo(basic_info);
}

/**
 * @brief TcpServerThread::parseChargeGunChargeInfo 解析充电枪充电信息
 * @param data   充电枪充电信息数据
 */
void TcpServerThread::parseChargeGunChargeInfo(const QByteArray &data)
{
    charge_gun_charge_info_t charge_info = GeneralInterface::decodeChargeInfo(data);
    // sendHeatReply(CHARGE_GUN_CHARGE_INFO_CMD, charge_info.GUNID);
    refreshChargingInfo(charge_info);

    sendHeatReply(CHARGE_GUN_CHARGE_INFO_CMD, charge_info.GUNID);
}

/**
 * @brief TcpServerThread::parseChargeGunStart  解析充电枪启动命令
 * @param data   充电枪启动命令数据
 */
void TcpServerThread::parseChargeGunStart(const QByteArray &data)
{
    REPLY_INFO reply_info = GeneralInterface::decodeReplyInfo(data);
    if (!reply_info.result) {
        LOG_WARNING("Charge gun start command failed to execute!");
        emit authResult(m_auth_gun_id, AuthError::AUTH_FAILD);
    } else {
        LOG_INFO("Charge gun start command executed successfully!");
        emit authResult(m_auth_gun_id, AuthError::SUCCESS);
    }

    emit chargeGunCtlReply(reply_info.result);
}

/**
 * @brief TcpServerThread::parseChargeGunStop   解析充电枪停止命令
 * @param data   充电枪停止命令数据
 */
void TcpServerThread::parseChargeGunStop(const QByteArray &data)
{
    REPLY_INFO reply_info = GeneralInterface::decodeReplyInfo(data);
    if (!reply_info.result) {
        LOG_WARNING("Charge gun stop command failed to execute!");
        emit authResult(m_auth_gun_id, AuthError::AUTH_FAILD);
    } else {
        LOG_INFO("Charge gun stop command executed successfully!");
        emit authResult(m_auth_gun_id, AuthError::SUCCESS);
    }

    emit chargeGunCtlReply(reply_info.result);
}

/**
 * @brief TcpServerThread::parseHeartbeatReply  解析心跳回复
 * @param data   心跳回复数据
 */
void TcpServerThread::parseHeartbeatReply(const QByteArray &data)
{
    REPLY_INFO reply_info = GeneralInterface::decodeReplyInfo(data);

    // 发送心跳回复
    QByteArray reply_data = GeneralInterface::encodeReplyInfo(reply_info);
    sendData(HEARTBEAT_REPLY_CMD, reply_data, m_trans_id);

    // 重置心跳定时器
    // resetHeartbeatTimer();
}

/**
 * @brief TcpServerThread::parseAuthResult  解析认证结果
 * @param data   认证结果数据
 */
void TcpServerThread::parseAuthResult(const QByteArray &data)
{
    REPLY_INFO reply_info = GeneralInterface::decodeReplyInfo(data);
    if (!reply_info.result) {
        LOG_WARNING("Charge gun auth command failed to execute!");
        emit authResult(m_auth_gun_id, AuthError::AUTH_FAILD);
    } else {
        LOG_INFO("Charge gun auth command executed successfully!");
        emit authResult(m_auth_gun_id, AuthError::SUCCESS);
    }

}

/**
 * @brief TcpServerThread::parseGunError    解析充电枪错误码
 * @param gun_error     充电枪错误码
 * @param gun_id        充电枪ID
 */
void TcpServerThread::parseGunError(const uint32_t &gun_error, const uint32_t &gun_id)
{
    auto error_map = parseErrorCodeUint32(gun_error);
    QString key = "";
    if (gun_id == CHARGE_GUN_DEFAULT_1) key = Global::Keys::GUN_ERROR_1;
    else if (gun_id == CHARGE_GUN_DEFAULT_2) key = Global::Keys::GUN_ERROR_2;

    if (gun_error != 0) {
        // qDebug() << QString("Gun error: %1").arg(error_map.value(gun_error));
    }
    GLOBALS->setValue(key, QVariant::fromValue(error_map));
}

/**
 * @brief TcpServerThread::parseGunState    解析充电枪状态码
 * @param gun_state    充电枪状态码
 * @param gun_id       充电枪ID
 */
void TcpServerThread::parseGunState(const uint32_t &gun_state, const uint32_t &gun_id)
{
    auto state_str = GeneralInterface::getStateDescriptions(gun_state);
    QString key = "";
    if (gun_id == CHARGE_GUN_DEFAULT_1) key = Global::Keys::GUN_STATE_1;
    else if (gun_id == CHARGE_GUN_DEFAULT_2) key = Global::Keys::GUN_STATE_2;

    // qDebug() << QString("Gun state: %1/%2").arg(QString::number(gun_state, 16), state_str);

    QMap<uint32_t, QString> state_map;
    state_map.insert(gun_state, state_str);
    GLOBALS->setValue(key, QVariant::fromValue(state_map));
}

/**
 * @brief TcpServerThread::parseGunType 解析充电枪类型
 * @param gun_type   充电枪类型
 * @param gun_id     充电枪ID
 */
void TcpServerThread::parseGunType(const uint32_t &gun_type, const uint32_t &gun_id)
{
    UINT8_QSTRING_MAP type_map;
    type_map.clear();
    switch (gun_type) {
    case GUNTYPE_NACS:
        type_map.insert(gun_type, "NACS");
        break;
    case GUNTYPE_CCS1:
        type_map.insert(gun_type, "CCS1");
        break;
    case GUNTYPE_CCS2:
        type_map.insert(gun_type, "CCS2");
        break;
    case GUNTYPE_CHADEMO:
        type_map.insert(gun_type, "CHAdeMO");
        break;
    case GUNTYPE_GBDC:
        type_map.insert(gun_type, "GBDC");
        break;
    default:
        type_map.insert(gun_type, "Unknown");
        break;
    }
    QString key = "";
    if (gun_id == CHARGE_GUN_DEFAULT_1) key = Global::Keys::GUN_TYPE_1;
    else if (gun_id == CHARGE_GUN_DEFAULT_2) key = Global::Keys::GUN_TYPE_2;

    // qDebug() << QString("Gun type: %1/%2").arg(QString::number(gun_type, 16), type_map.value(gun_type));
    GLOBALS->setValue(key, QVariant::fromValue(type_map));
}

/**
 * @brief TcpServerThread::refreshBasicInfo 刷新充电枪基本信息
 * @param info   充电枪基本信息
 */
void TcpServerThread::refreshBasicInfo(const BASIC_INFO &info)
{
    // 根据 GUNID 将充电枪基本信息存入全局变量中
    if (info.GUNID == CHARGE_GUN_DEFAULT_1) GLOBALS->setValue(Global::Keys::GUN_BASIC_INFO_1, QVariant::fromValue(info));
    else if (info.GUNID == CHARGE_GUN_DEFAULT_2) GLOBALS->setValue(Global::Keys::GUN_BASIC_INFO_2, QVariant::fromValue(info));
}

/**
 * @brief TcpServerThread::refreshChargingInfo  刷新充电信息
 * @param info   充电信息
 */
void TcpServerThread::refreshChargingInfo(const CHARGING_INFO &info)
{
    // 根据 GUNID 将充电枪充电信息存入全局变量中
    if (info.GUNID == CHARGE_GUN_DEFAULT_1) GLOBALS->setValue(Global::Keys::CHARGING_INFO_1, QVariant::fromValue(info));
    else if (info.GUNID == CHARGE_GUN_DEFAULT_2) GLOBALS->setValue(Global::Keys::CHARGING_INFO_2, QVariant::fromValue(info));
}

/**
 * @brief TcpServerThread::initErrorDescriptions    初始化错误码描述
 */
void TcpServerThread::initErrorDescriptions()
{
    m_errorDescriptions.insert(GUNERROR_NO_ERROR,               tr("NO Error"));
    m_errorDescriptions.insert(GUNERROR_BOX_OVERTEMP,           tr("Box is overheated"));
    m_errorDescriptions.insert(GUNERROR_SMOKE_ALARM,            tr("Smoke detector alarm"));
    m_errorDescriptions.insert(GUNERROR_LGPTA_ALARM,            tr("Alarm of lightning protector A"));
    m_errorDescriptions.insert(GUNERROR_LGPTB_ALARM,            tr("Alarm of lightning protector B"));
    m_errorDescriptions.insert(GUNERROR_FANA_ALARM,             tr("Fan A alarm"));
    m_errorDescriptions.insert(GUNERROR_FANB_ALARM,             tr("Fan B alarm"));
    m_errorDescriptions.insert(GUNERROR_FANC_ALARM,             tr("Fan C alarm"));
    m_errorDescriptions.insert(GUNERROR_LIQC_ALARM,             tr("Water cooling system alarm"));
    m_errorDescriptions.insert(GUNERROR_EMG_ALARM,              tr("Emergency stop alarm"));
    m_errorDescriptions.insert(GUNERROR_WAT_ALARM,              tr("Water flooding alarm"));
    m_errorDescriptions.insert(GUNERROR_GAT_ALARM,              tr("Access control alarm"));
    m_errorDescriptions.insert(GUNERROR_HPUMP_ALARM,            tr("Heat pump system alarm"));
    m_errorDescriptions.insert(GUNERROR_FUSE_ALARM,             tr("Fuse alarm"));
    m_errorDescriptions.insert(GUNERROR_STALL_ALARM,            tr("Electronic lock block alarm"));
    m_errorDescriptions.insert(GUNERROR_CONTACTOR_FAULT,        tr("Contactor is not moving"));
    m_errorDescriptions.insert(GUNERROR_LINE_OVERTEMP,          tr("Gun wire is overheated"));
    m_errorDescriptions.insert(GUNERROR_HANDSHAKE_FAULT,        tr("Pile handshake failed"));
    m_errorDescriptions.insert(GUNERROR_INSULATION_FAULT,       tr("Insulation test failure"));
    m_errorDescriptions.insert(GUNERROR_PRECHARGE_FAULT,        tr("Precharge failure"));
    m_errorDescriptions.insert(GUNERROR_CHARGING_FAULT,         tr("Charge failure"));
    m_errorDescriptions.insert(GUNERROR_BMS_VOLTAGE_INVERSE,    tr("BMS battery voltage reverse connection"));
    m_errorDescriptions.insert(GUNERROR_BMS_CONTACTOR_FAULT,    tr("BMS contactor is inactive"));
    m_errorDescriptions.insert(GUNERROR_BMS_VOLTAGE_MISSTACH,   tr("BMS voltage misadjustment or excessive wave"));
    m_errorDescriptions.insert(GUNERROR_BMS_CURRENT_MISSTACH,   tr("BMS current misregulation or overvoltage"));
}

/**
 * @brief TcpServerThread::initTypeDescriptions 初始化枪类型描述
 */
void TcpServerThread::initTypeDescriptions()
{
    m_typeDescriptions.insert(GUNTYPE_NACS,     tr("NACS"));
    m_typeDescriptions.insert(GUNTYPE_CCS1,     tr("CCS1"));
    m_typeDescriptions.insert(GUNTYPE_CCS2,     tr("CCS2"));
    m_typeDescriptions.insert(GUNTYPE_CHADEMO,  tr("CHAdeMO"));
    m_typeDescriptions.insert(GUNTYPE_GBDC,     tr("GBDC"));
}

/**
 * @brief TcpServerThread::sendHeatReply    发送心跳回复
 * @param cmd        命令
 * @param gun_id     充电枪ID
 */
void TcpServerThread::sendHeatReply(const uint8_t cmd, const int &gun_id)
{
    REPLY_INFO reply_info;
    reply_info.result = 1;

    // 发送心跳回复
    QByteArray reply_data = GeneralInterface::encodeReplyInfo(reply_info);
    sendData(cmd, reply_data, m_trans_id);

    // 重置心跳定时器
    resetHeartbeatTimer(gun_id);
}

/**
 * @brief TcpServerThread::parseCodeBits    解析比特位
 * @param code                  错误码
 * @param bitDescriptions       比特位描述
 * @return   比特位描述
 */
UINT8_QSTRING_MAP TcpServerThread::parseCodeBits(uint32_t code, const UINT8_QSTRING_MAP &bitDescriptions)
{
    UINT8_QSTRING_MAP result;

    // 遍历所有比特位
    for (uint8_t bit = 0; bit < 32; bit ++) {
        // 检查当前比特位是否置位
        if (code & (1u << bit)) {
            // 查找该比特位对应的错误描述
            auto it = bitDescriptions.constFind(bit);
            if (it != bitDescriptions.constEnd()) {
                // 找到描述，添加到结果容器
                result.insert(bit, it.value());
            } else {
                // 未找到描述, 使用默认信息
                result.insert(0xFF, QString("Unknown %1").arg(bit));
            }
        }
    }

    return result;
}

/**
 * @brief TcpServerThread::parseErrorCodeUint32 解析错误码
 * @param code               错误码
 * @return   错误码描述
 */
UINT32_QSTRING_MAP TcpServerThread::parseErrorCodeUint32(uint32_t code)
{
    UINT32_QSTRING_MAP result;
    if (code > static_cast<size_t>(m_tcu_cfg.error_code_note.size()) || code == 0) return UINT32_QSTRING_MAP();
    QString code_str = QString("0x%1").arg(code, 8, 16, QChar('0'));
    result.insert(code, code_str + ":" + getErrorNote(code));
    return result;
}

/**
 * @brief TcpServerThread::parseStateCodeUint32 解析状态码
 * @param code             状态码
 * @return   状态码描述
 */
UINT32_QSTRING_MAP TcpServerThread::parseStateCodeUint32(uint32_t code)
{
    UINT32_QSTRING_MAP result;
    if (code > static_cast<size_t>(m_tcu_cfg.error_code_note.size()) || code == 0) return UINT32_QSTRING_MAP();
    QString code_str = QString("0x%1").arg(code, 8, 16, QChar('0'));
    result.insert(code, code_str + ":" + getErrorNote(code));
    return result;
}

/**
 * @brief TcpServerThread::getErrorNote 获取错误码描述
 * @param code  错误码
 * @return   错误码描述
 */
QString TcpServerThread::getErrorNote(const uint32_t &code)
{
    foreach (const ERROR_NOTE& error, m_tcu_cfg.error_code_note) {
        if (error.error_code == code) {
            return error.error_note;
        }
    }

    return QString("");
}

/**
 * @brief TcpServerThread::getClientInfo    获取客户端信息
 * @return   客户端信息
 */
QString TcpServerThread::getClientInfo() const
{
    if (!m_client) {
        return "Unknown client";
    }
    return QString("%1:%2").arg(m_client->peerAddress().toString()).arg(m_client->peerPort());
}

/**
 * @brief TcpServerThread::handleNewConnection  处理新的连接
 */
void TcpServerThread::handleNewConnection()
{
    // 如果已有客户端连接，拒绝新的连接
    if (m_client) {
        QMetaObject::invokeMethod(m_server, [this]() {
            QTcpSocket *socket = m_server->nextPendingConnection();
            if (socket) {
                socket->disconnectFromHost();
                socket->deleteLater();
            }
        }, Qt::QueuedConnection);
        return;
    }

    // 在工作线程中创建和初始化socket
    QMetaObject::invokeMethod(m_server, [this]() {
        QTcpSocket *newSocket = m_server->nextPendingConnection();
        if (!newSocket) {
            return;
        }

        // 确保socket在工作线程中
        newSocket->moveToThread(m_workerThread);

        // 连接信号
        connect(newSocket, &QTcpSocket::readyRead,      this,   &TcpServerThread::handleReadyRead);
        connect(newSocket, &QTcpSocket::disconnected,   this,   &TcpServerThread::handleClientDisconnected);
        connect(newSocket, &QTcpSocket::errorOccurred,  this,   &TcpServerThread::handleError);

        // 初始化数据接收状态
        auto gun_num = ConfigManager::instance()->ccu_cfg().GUN_Numb;
        for (int index = 1; index <= gun_num; index++) {
            m_dataReceived[index] = false;
        }

        // 启动心跳定时器
        for (auto timer : m_heartbeatTimer) {
            QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection,
                Q_ARG(int, m_tcu_cfg.time_out.tcp_heartbeat * 1000));
        }

        // 使用原子操作更新m_client
        QMetaObject::invokeMethod(this, [this, newSocket]() {
            m_client = newSocket;
            m_isConnected = true;
            LOG_INFO(QString("New client connection : %1").arg(getClientInfo()));
            emit clientConnected();
        }, Qt::QueuedConnection);
    }, Qt::QueuedConnection);
}

/**
 * @brief TcpServerThread::handleClientDisconnected 处理客户端断开连接
 */
void TcpServerThread::handleClientDisconnected()
{
    removeClient();
    emit clientDisconnected();
}

/**
 * @brief TcpServerThread::handleReadyRead  处理客户端发送的数据
 */
void TcpServerThread::handleReadyRead()
{
    if (!m_client) {
        return;
    }

    m_recvData.append(m_client->readAll());
    while (true) {
        // 1. 判断是否有长度头
        if (m_recvData.size() < MESSAGE_HEAD_LENGTH)
            break;

        // 2. 取出长度头
        // 处理报文帧头
        MSG_HEAD msg_head;
        msg_head.trans_id   = GeneralInterface::toUInt16(m_recvData.mid(0, 2));
        msg_head.proto_id   = GeneralInterface::toUInt16(m_recvData.mid(2, 2));
        msg_head.length     = GeneralInterface::toUInt16(m_recvData.mid(4, 2));
        msg_head.unit_id    = GeneralInterface::toUInt8(m_recvData.mid(6, 1));
        msg_head.cmd        = GeneralInterface::toUInt8(m_recvData.mid(7, 1));

        // 3. 判断是否有完整消息
        if (m_recvData.size() < MESSAGE_HEAD_LENGTH + msg_head.length)
            break;

        // 4. 取出完整消息
        QByteArray msg = m_recvData.mid(0, MESSAGE_HEAD_LENGTH+msg_head.length);

        // 5. 处理消息
        parseClientMsg(msg);

        // 6. 移除已处理部分
        m_recvData.remove(0, MESSAGE_HEAD_LENGTH + msg_head.length);
    }
}

/**
 * @brief TcpServerThread::handleError  处理socket错误
 * @param socketError    错误码
 */
void TcpServerThread::handleError(QAbstractSocket::SocketError socketError)
{
    QString errorMsg = QString("Socket error %1: %2").arg(socketError).arg(m_client->errorString());
    LOG_ERROR(errorMsg);
    emit errorOccurred(TcpError::INVALID_SOCKET, errorMsg);
}

/**
 * @brief TcpServerThread::removeClient 移除客户端
 */
void TcpServerThread::removeClient()
{
    if (m_client) {
        // 在socket所属线程中执行断开连接
        QMetaObject::invokeMethod(m_client, [this]() {
            m_client->disconnectFromHost();
            if (m_client->state() != QAbstractSocket::UnconnectedState) {
                m_client->waitForDisconnected(1000);
            }
            m_client->deleteLater();
            m_client = nullptr;
            m_isConnected = false;

            // 重置所有充电枪的数据接收状态
            for (auto it = m_dataReceived.begin(); it != m_dataReceived.end(); ++it) {
                it.value() = false;
            }
        }, Qt::QueuedConnection);
    }

    // 停止所有定时器
    for (auto timer : std::as_const(m_heartbeatTimer)) {
        if (timer->isActive()) {
            QMetaObject::invokeMethod(timer, "stop", Qt::BlockingQueuedConnection);
        }
    }
}

/**
 * @brief TcpServerThread::resetHeartbeatTimer  重置心跳定时器
 * @param gun_id     充电枪ID
 */
void TcpServerThread::resetHeartbeatTimer(const int &gun_id)
{
    if (m_heartbeatTimer.contains(gun_id)) {
        QMetaObject::invokeMethod(m_heartbeatTimer[gun_id], "start", Qt::QueuedConnection);
    }
}
