#include "GeneralInterface.h"

#include <QTime>
#include <QRect>
#include <QPoint>
#include <QScreen>
#include <QDateTime>
#include <QCheckBox>
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsProxyWidget>
#include <QParallelAnimationGroup>
#include <QPropertyAnimation>
#include <QDataStream>
#include <QScroller>
#include <QPainter>
#include <unistd.h>

#include "Globals.h"
#include "ConfigManager.h"
#include "OtherSettings/log/FormLogView.h"
#include "VersionManager.h"

template<typename T>
T GeneralInterface::toInt(const QByteArray &data, int offset, bool networkOrder)
{
    if ((offset + sizeof(T)) > static_cast<size_t>(data.size())) {
        return 0;
    }

    T value;
    memcpy(&value, data.constData() + offset, sizeof(T));

    if (networkOrder) {
        if constexpr (sizeof(T) == 2) {
            return qFromBigEndian(value);
        } else if constexpr (sizeof(T) == 4) {
            return qFromBigEndian(value);
        } else if constexpr (sizeof(T) == 8) {
            return qFromBigEndian<qint64>(value);
        }
    }

    return value;
}

/**
 * @brief 将QByteArray中的数据转换为uint8_t类型
 *
 * @param   data    QByteArray对象，包含要转换的数据
 * @param   offset  数据在QByteArray中的偏移量
 * @return  uint8_t 转换后的uint8_t类型数据
 */
uint8_t GeneralInterface::toUInt8(const QByteArray &data, int offset)
{
    return toInt<uint8_t>(data, offset);
}

/**
 * @brief 将QByteArray中的数据转换为uint16_t类型
 *
 * @param   data            QByteArray对象，包含要转换的数据
 * @param   offset          数据在QByteArray中的偏移量
 * @param   networkOrder    是否使用网络字节序
 * @return  uint16_t        转换后的uint16_t值
 */
uint16_t GeneralInterface::toUInt16(const QByteArray &data, int offset, bool networkOrder)
{
    return toInt<uint16_t>(data, offset, networkOrder);
}

/**
 * @brief 将QByteArray中的数据转换为uint32_t类型
 *
 * @param   data            QByteArray对象，包含要转换的数据
 * @param   offset          数据在QByteArray中的偏移量
 * @param   networkOrder    是否使用网络字节序
 * @return  uint32_t        转换后的uint32_t值
 */
uint32_t GeneralInterface::toUInt32(const QByteArray &data, int offset, bool networkOrder) {
    return toInt<uint32_t>(data, offset, networkOrder);
}

/**
 * @brief 将QByteArray转换为uint64_t类型
 *
 * @param data          QByteArray对象，包含要转换的数据
 * @param offset        数据在QByteArray中的偏移量
 * @param networkOrder  是否使用网络字节序
 * 
 * @return uint64_t 转换后的uint64_t类型数据
 */
uint64_t GeneralInterface::toUInt64(const QByteArray &data, int offset, bool networkOrder)
{
    return toInt<uint64_t>(data, offset, networkOrder);
}

/**
 * @brief   GeneralInterface::networkStructToByteArray    将MSG_HEAD结构体转换为网络字节序的字节数组
 * @param   data  MSG_HEAD结构体
 * @return  QByteArray
 */
QByteArray GeneralInterface::networkStructToByteArray(const MSG_HEAD &data)
{
    // 将MSG_HEAD结构体转换为网络字节序的字节数组
    MSG_HEAD networkData;
    networkData.trans_id    = qToBigEndian(data.trans_id);
    networkData.proto_id    = qToBigEndian(data.proto_id);
    networkData.length      = qToBigEndian(data.length);
    networkData.unit_id     = qToBigEndian(data.unit_id);
    networkData.cmd         = qToBigEndian(data.cmd);

    // 返回转换后的字节数组
    return QByteArray(reinterpret_cast<const char*>(&networkData), sizeof(MSG_HEAD));
}

/**
 * @brief   GeneralInterface::encodeValue 将数据编码为指定长度的字节数组
 * @param   data  要编码的数据
 * @param   length    数据的长度
 * @return  编码后的字节数组
 */
template<typename T>
QByteArray GeneralInterface::encodeValue(T &data, const uint8_t &length)
{
    QByteArray result;
    auto tempData = qToBigEndian(data);
    result.append(0x80 + sizeof(data));
    result.append(length);
    result.append(QByteArray(reinterpret_cast<const char*>(&tempData), sizeof(T)));
    return result;
}

/**
 * @brief   GeneralInterface::decodeValue 将字节数组解码为指定类型的数据
 * @param   data  字节数组
 * @return  解码后的数据
 */
template<typename T>
T GeneralInterface::decodeValue(const QByteArray &data)
{
    return toInt<T>(data);
}

/**
 * @brief   GeneralInterface::encodeStartChargeGunInfo    将START_CHARGE_CMD结构体编码为字节数组
 * @param   data  START_CHARGE_CMD结构体
 * @return  编码后的字节数组
 */
QByteArray GeneralInterface::encodeStartChargeGunInfo(const START_CHARGE_CMD &data)
{
    QByteArray ctl_array;
    ctl_array.append(encodeValue<const uint32_t>(data.GUNID, 1));
    ctl_array.append(0x81);
    ctl_array.append(sizeof(data.EMID));
    ctl_array.append(QByteArray(reinterpret_cast<const char*>(&data.EMID), sizeof(data.EMID)));
    ctl_array.append(encodeValue<const uint32_t>(data.requestKWs, 1));
    ctl_array.append(encodeValue<const uint32_t>(data.requestMinutes, 1));
    ctl_array.append(encodeValue<const uint32_t>(data.requestSOC, 1));
    ctl_array.append(encodeValue<const uint32_t>(data.authorizationResult, 1));
    return ctl_array;
}

/**
 * @brief   GeneralInterface::encodeStopChargeGunInfo 将STOP_CHARGE_CMD结构体编码为字节数组
 * @param   data  STOP_CHARGE_CMD结构体
 * @return  编码后的字节数组
 */
QByteArray GeneralInterface::encodeStopChargeGunInfo(const STOP_CHARGE_CMD &data)
{
    QByteArray ctl_array;
    ctl_array.append(encodeValue<const uint32_t>(data.GUNID, 1));
    ctl_array.append(0x81);
    ctl_array.append(sizeof(data.EMID));
    ctl_array.append(QByteArray(reinterpret_cast<const char*>(&data.EMID), sizeof(data.EMID)));
    ctl_array.append(encodeValue<const uint32_t>(data.authorizated, 1));
    return ctl_array;
}

/**
 * @brief   GeneralInterface::decodeChargeBasicInfo   将字节数组解码为charge_gun_basic_info_t结构体
 * @param   data  字节数组
 * @return  charge_gun_basic_info_t结构体
 */
charge_gun_basic_info_t GeneralInterface::decodeChargeBasicInfo(const QByteArray &data)
{
    charge_gun_basic_info_t basicInfo;
    int start_index = 2;

    basicInfo.GUNID     = decodeValue<uint32_t>(data.mid(start_index, sizeof(uint32_t)));
    start_index += (sizeof(uint32_t) + 2);

    basicInfo.GUN_Error = decodeValue<uint32_t>(data.mid(start_index, sizeof(uint32_t)));
    start_index += (sizeof(uint32_t) + 2);

    basicInfo.GUN_State = decodeValue<uint32_t>(data.mid(start_index, sizeof(uint32_t)));
    start_index += (sizeof(uint32_t) + 2);

    basicInfo.GUN_Type  = decodeValue<uint32_t>(data.mid(start_index, sizeof(uint32_t)));
    basicInfo.BOX_temp  = decodeValue<uint32_t>(data.mid(start_index, sizeof(uint32_t)));

    return basicInfo;
}

/**
 * @brief   GeneralInterface::decodeChargeInfo    将字节数组解码为charge_gun_charge_info_t结构体
 * @param   data  字节数组
 * @return  charge_gun_charge_info_t结构体
 */
charge_gun_charge_info_t GeneralInterface::decodeChargeInfo(const QByteArray &data)
{
    charge_gun_charge_info_t charge_info;
    int start_index = 2;

    charge_info.GUNID           = decodeValue<uint32_t>(data.mid(start_index, sizeof(uint32_t)));
    start_index += (sizeof(uint32_t) + 2);

    charge_info.transactionId   = decodeValue<uint32_t>(data.mid(start_index, sizeof(uint32_t)));
    start_index += (sizeof(uint32_t) + 2);

    charge_info.SOC             = decodeValue<uint32_t>(data.mid(start_index, sizeof(uint32_t)));
    start_index += (sizeof(uint32_t) + 2);

    charge_info.startUTC        = decodeValue<uint32_t>(data.mid(start_index, sizeof(uint32_t)));
    start_index += (sizeof(uint32_t) + 2);

    charge_info.now_UTC         = decodeValue<uint32_t>(data.mid(start_index, sizeof(uint32_t)));
    start_index += (sizeof(uint32_t) + 2);

    charge_info.startKW         = decodeValue<uint32_t>(data.mid(start_index, sizeof(uint32_t)));
    start_index += (sizeof(uint32_t) + 2);

    charge_info.now_KW          = decodeValue<uint32_t>(data.mid(start_index, sizeof(uint32_t)));
    start_index += (sizeof(uint32_t) + 2);

    charge_info.GUNLine_temp0   = decodeValue<uint32_t>(data.mid(start_index, sizeof(uint32_t)));
    start_index += (sizeof(uint32_t) + 2);

    charge_info.GUNLine_temp1   = decodeValue<uint32_t>(data.mid(start_index, sizeof(uint32_t)));
    start_index += (sizeof(uint32_t) + 2);

    charge_info.powerKW         = decodeValue<uint32_t>(data.mid(start_index, sizeof(uint32_t)));
    start_index += (sizeof(uint32_t) + 2);

    charge_info.voltage         = decodeValue<uint32_t>(data.mid(start_index, sizeof(uint32_t)));
    start_index += (sizeof(uint32_t) + 2);

    charge_info.current         = decodeValue<uint32_t>(data.mid(start_index, sizeof(uint32_t)));

    return charge_info;
}

/**
 * @brief   GeneralInterface::decodeReplyInfo 将字节数组解码为REPLY_INFO结构体
 * @param   data  字节数组
 * @return  REPLY_INFO结构体
 */
REPLY_INFO GeneralInterface::decodeReplyInfo(const QByteArray& data)
{
    REPLY_INFO info;
    int start_index = 2;
    info.result = decodeValue<uint32_t>(data.mid(start_index, sizeof(uint32_t)));

    return info;
}

/**
 * @brief   GeneralInterface::encodeReplyInfo 将REPLY_INFO结构体编码为字节数组
 * @param   info  REPLY_INFO结构体
 * @return  编码后的字节数组
 */
QByteArray GeneralInterface::encodeReplyInfo(const REPLY_INFO& info)
{
    QByteArray result;
    result.append(encodeValue<const uint32_t>(info.result, 1));

    return result;
}

/**
 * @brief GeneralInterface::setCheckBoxChecked  设置widget下所有QCheckBox的checked属性
 * @param widget    
 * @param checked   
 */
void GeneralInterface::setCheckBoxChecked(const QWidget *widget, const bool &checked)
{
    QList<QCheckBox*> checkBoxes = widget->findChildren<QCheckBox*>();
    if (checkBoxes.isEmpty()) return;

    foreach (QCheckBox* checkBox, checkBoxes) {
        checkBox->setChecked(checked);
    }
}

/**
 * @brief GeneralInterface::setTouchScroller    设置QScrollArea的滚动方式为触摸滚动
 * @param area  
 */
void GeneralInterface::setTouchScroller(QScrollArea *area)
{
    QScroller::grabGesture(area,              QScroller::TouchGesture);
    QScroller::grabGesture(area->viewport(),  QScroller::LeftMouseButtonGesture);
}

/**
 * @brief   GeneralInterface::getWindowTitle  获取窗口标题
 * @param   type  窗口类型
 * @return  窗口标题
 */
QString GeneralInterface::getWindowTitle(const int &type)
{
    switch (type) {
    case FormItem::GENERAL:     return tr("General Log");
    case FormItem::OCPP16:      return tr("OCPP 1.6 Log");
    case FormItem::SLAVE:       return tr("Lower machine log");
    default:                    return QString("");
    }
}

/**
 * @brief   GeneralInterface::getLogFilePath  获取日志文件路径
 * @param   type  窗口类型
 * @return  日志文件路径
 */
QString GeneralInterface::getLogFilePath(const int &type)
{
    switch (type) {
    case FormItem::GENERAL:     return ConfigManager::instance()->tcu_cfg().log_config.general_log_path;
    case FormItem::OCPP16:      return ConfigManager::instance()->tcu_cfg().log_config.ocpp16_log_path;
    case FormItem::SLAVE:       return ConfigManager::instance()->tcu_cfg().log_config.slave_log_path;
    default:                    return QString("");
    }
}

/**
 * @brief   GeneralInterface::getStateDescriptions    获取状态描述
 * @param   code   状态码
 * @return  状态描述
 */
QString GeneralInterface::getStateDescriptions(uint32_t code)
{
    switch (code) {
    case GUNSTATE_IDLE:     return "Stand By";
    case GUN_PLUGOUT:       return "Plug Out";
    case GUN_PLUGIN:        return "Plug In";
    case GUN_STARTUP:       return "Start Up";
    case GUN_ELOCKED:       return "Elocked";
    case GUN_AUTHORIZED:    return "Authorized";
    case GUN_PARAMETERS:    return "Parameters";
    case GUN_INSULATION:    return "Insulation";
    case GUN_PRECHARGE:     return "Precharge";
    case GUN_CHARGING:      return "Charging";
    case GUN_SUSPEND:       return "Suspend";
    case GUN_STOPING:       return "Stop";
    case GUN_UNKNOW:        return "Unknow";
    default:                return "NULL";
    }
}

/**
 * @brief   GeneralInterface::getGuiState 根据表单类型和状态码获取GUI状态
 * @param   form    表单类型
 * @param   state   状态码
 * @return  GUI状态
 */
gui_state_enum GeneralInterface::getGuiState(const charge_prepare_enum &form, const int &state)
{
    switch (form) {
    case PLUG_IN:           return CHARGE_GUN_AVAILABLE;
    case AUTHENTICATION:    return getGuiStateAuthForm(state);
    case CHARGE_PREPARE:    return getGuiStatePrepareForm(state);
    case CHARGING_FORM:     return getGuiStateChargingForm(state);
    case FINISH_FORM:       return RETURN_GUN;
    case ERROR_FORM:        return getGuiStateErrorForm();
    default:                return UNKOWN_STATE;
    }
}

/**
 * @brief   GeneralInterface::getGuiStateAuthForm 根据状态码获取授权表单的GUI状态
 * @param   state 状态码
 * @return  授权表单的GUI状态
 */
gui_state_enum GeneralInterface::getGuiStateAuthForm(const int &state)
{
    switch (state) {
    case AuthType::QR:              return AUTHORIZATION_QR;
    case AuthType::CARD:            return AUTHORIZATION_ID_CARD;
    case AuthType::QR_OR_CARD:      return AUTHORIZATION_QR_ID_CARD;
    case AuthType::NO_CARD:         return WAITING_NO_ID_CARD;
    case AuthType::NO_QR_OR_CARD:   return WAITING_NO_ID_CARD_QR;
    default:                        return UNKOWN_STATE;
    }
}

/**
 * @brief   GeneralInterface::getGuiStatePrepareForm  根据状态码获取准备表单的GUI状态
 * @param   state 状态码
 * @return  准备表单的GUI状态
 */
gui_state_enum GeneralInterface::getGuiStatePrepareForm(const int &state)
{
    switch (state) {
    case 0:     return RETRY_OR_RETURN_GUN;
    case 1:     return SCAN_QR_OR_RETURN_GUN;
    case 2:     return CARD_AUTHORIZATION_FAILED;
    case 3:     return CHANGE_CARD;
    case 4:     return BALANCE_NO_START;
    case 6:     return TOP_UP_RETRY;
    case 7:     return PREPARE_HANDSHAKING;
    case 8:     return HANDSHAKING;
    case 9:     return CONFIGUING;
    case 10:    return START_CHARGING;
    case 11:    return UNPLUG_RETRY_OR_CHANGE;
    default:    return UNKOWN_STATE;
    }
}

/**
 * @brief   GeneralInterface::getGuiStateChargingForm 根据状态码获取充电表单的GUI状态
 * @param   state 状态码
 * @return  充电表单的GUI状态
 */
gui_state_enum GeneralInterface::getGuiStateChargingForm(const int &state)
{
    switch (state) {
    case 0:     return RETURN_GUN;
    default:    return UNKOWN_STATE;
    }
}

/**
 * @brief   GeneralInterface::getGuiStateFinishForm   根据状态码获取完成表单的GUI状态
 * @param   state 状态码
 * @return  完成表单的GUI状态
 */
gui_state_enum GeneralInterface::getGuiStateFinishForm(const int &state)
{
    switch (state) {
    case 0:     return RETURN_GUN;
    default:    return UNKOWN_STATE;
    }
}

/**
 * @brief   GeneralInterface::getGuiStateErrorForm    根据状态码获取错误表单的GUI状态
 * @param   state 状态码
 * @return  错误表单的GUI状态
 */
gui_state_enum GeneralInterface::getGuiStateErrorForm(const int &state)
{
    switch (state) {
    case 0:     return RETURN_GUN;
    case 1:     return CHARGE_GUN_UNAVILABLE;
    case 2:     return OUT_OF_SERVICE;
    case 3:     return MAX_POWER_LIMIT;
    default:    return UNKOWN_STATE;
    }
}

/**
 * @brief   GeneralInterface::getChargeProgress   根据表单类型获取充电进度
 * @param   form  表单类型
 * @return  充电进度
 */
charge_progress_enum GeneralInterface::getChargeProgress(const charge_prepare_enum &form)
{
    switch (form) {
    case PLUG_IN:           return PLUG_IN_PROGRESS;
    case CHARGING_FORM:     return CHARGING_PROGRESS;
    case CHARGE_PREPARE:    return AUTHORIZATION_PROGRESS;
    case AUTHENTICATION:    return AUTHORIZATION_PROGRESS;
    case FINISH_FORM:       return FINISHED_PROGRESS;
    default:                return UNKNOWN_PROGRESS;
    }
}

/**
 * @brief   GeneralInterface::getChangedGunID 根据枪ID获取另一把枪的ID
 * @param   gun_id    枪ID
 * @return  另一把枪的ID
 */
int GeneralInterface::getChangedGunID(const int &gun_id)
{
    switch (gun_id) {
    case CHARGE_GUN_DEFAULT_1:  return CHARGE_GUN_DEFAULT_2;
    case CHARGE_GUN_DEFAULT_2:  return CHARGE_GUN_DEFAULT_1;
    default:                    return 0;
    }
}

/**
 * @brief   GeneralInterface::getMaxHeight    获取widget的最大高度
 * @param   widget
 * @return  widget的最大高度
 */
int GeneralInterface::getMaxHeight(QWidget *widget)
{
    if (!widget) return 0;

    // 获取widget在全局的底部y坐标
    QPoint globalBottomLeft = widget->mapToGlobal(QPoint(0, widget->height()));

#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
    // Qt5.10及以上推荐用QScreen
    QScreen *screen = widget->screen();
    if (!screen) screen = QApplication::primaryScreen();
    QRect available = screen->availableGeometry();
#else
    // Qt5.9及以下用QDesktopWidget
    QRect available = QApplication::desktop()->availableGeometry(widget);
#endif

    int maxHeight = available.bottom() - globalBottomLeft.y();
    return maxHeight > 0 ? maxHeight : 0;
}

/**
 * @brief GeneralInterface::initTimezoneComboBox    初始化时区下拉框
 * @param combox    
 */
void GeneralInterface::initTimezoneComboBox(CustomComboBox *combox)
{
    QStringList timezone_list;
    timezone_list << "Asia/Shanghai"
                  << "Asia/Tokyo"
                  << "Asia/Seoul"
                  << "Asia/Kolkata"
                  << "Asia/Singapore"
                  << "Asia/Bangkok"
                  << "Asia/Kuala_Lumpur"
                  << "Europe/London"
                  << "Europe/Berlin"
                  << "Europe/Paris"
                  << "Europe/Rome"
                  << "Europe/Madrid"
                  << "Europe/Moscow"
                  << "America/New_York"
                  << "America/Los_Angeles"
                  << "America/Toronto"
                  << "America/Sao_Paulo"
                  << "America/Mexico_City";
    combox->addItems(timezone_list);
}

/**
 * @brief GeneralInterface::initLanguageComboBox    初始化语言下拉框
 * @param combox    
 */
void GeneralInterface::initLanguageComboBox(CustomComboBox *combox)
{
    QStringList timezone_list;
    timezone_list << "Chinese (Simplified)"
                  << "English (US)";
    combox->addItems(timezone_list);
}

/**
 * @brief GeneralInterface::clearGridLayoutChiledren    清空QGridLayout的子控件
 * @param layout    
 */
void GeneralInterface::clearGridLayoutChiledren(QGridLayout *layout)
{
    if (!layout) return;

    // 删除所有子控件（widget）
    while (QLayoutItem* item = layout->takeAt(0)) {
        if (QWidget* widget = item->widget()) {
            layout->removeWidget(widget);
            widget->deleteLater();  // 安全删除 widget
        } else if (QLayout* childLayout = item->layout()) {
            clearGridLayoutChiledren(qobject_cast<QGridLayout*>(childLayout));  // 递归删除子 layout
        }
        layout->removeItem(item);
        delete item;  // 删除 QLayoutItem 本身
    }

    for(int row = 0; row < layout->rowCount(); row ++) {
        layout->setRowStretch(row, 0);
    }

    layout->update();
}

/**
 * @brief GeneralInterface::gridLayoutAddWidget 向QGridLayout中添加控件
 * @param layout    
 * @param widget    
 */
void GeneralInterface::gridLayoutAddWidget(QGridLayout *layout, QWidget *widget, int row, int col)
{
    if (row == -1) row = layout->rowCount();
    layout->addWidget(widget, row, col);
    layout->setRowStretch(row, col);
}

/**
 * @brief GeneralInterface::gridLayoutAddStrtch 向QGridLayout中添加弹簧
 * @param layout
 */
void GeneralInterface::gridLayoutAddStrtch(QGridLayout *layout)
{
    int row = layout->rowCount();
    // 在最后一行添加弹簧（spacer），让控件靠上
    QSpacerItem* vSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
    layout->addItem(vSpacer, row, 0, 1, layout->columnCount());
    layout->setRowStretch(row, 1);
}

/**
 * @brief GeneralInterface::getChargingProfilePurposeIndex  根据充电配置目的获取索引
 * @param purpose    充电配置目的
 * @return
 */
int GeneralInterface::getChargingProfilePurposeIndex(const QString &purpose)
{
    if (purpose == ChargingProfiles::Purpose::CHARGE_POINT_MAX_PROFILE) {
        return Workspace::Settings::Ocpp::ChargingProfiles::CHARGE_POINT_MAX_PROFILE;
    } else if (purpose == ChargingProfiles::Purpose::TX_DEFAULT_PROFILE) {
        return Workspace::Settings::Ocpp::ChargingProfiles::TX_DEFAULT_PROFILE;
    } else if (purpose == ChargingProfiles::Purpose::TX_PROFILE) {
        return Workspace::Settings::Ocpp::ChargingProfiles::TX_PROFILE;
    }

    return 0;
}

/**
 * @brief GeneralInterface::getChargingProfileByPurpose 根据充电配置目的获取充电配置
 * @param data  
 * @param dataList
 * @param purpose
 * @return
 */
bool GeneralInterface::getChargingProfileByPurpose(charging_profiles_detail_info_t &data, const QList<charging_profiles_detail_info_t>& dataList, const QString &purpose)
{
    QMap<QString, QPair<int, charging_profiles_detail_info_t>> stats;

    for (const auto& item : std::as_const(dataList)) {
        if (stats.contains(item.chargingProfilePurpose)) {
            auto& tempData = stats[item.chargingProfilePurpose];
            tempData.first++;
            if (tempData.second.stackLevel < item.stackLevel) {
                tempData.second = item;
            }
        } else {
            stats.insert(item.chargingProfilePurpose, {1, item});
        }
    }

    if (stats.contains(purpose)) {
        data = stats.value(purpose).second;
    }

    return stats.contains(purpose);
}

/**
 * @brief GeneralInterface::chargingProfileToMap    充电配置转map
 * @param dataList  
 * @return
 */
QVARIANTMAP_INT_MAP GeneralInterface::chargingProfileToMap(const QList<charging_profiles_detail_info_t> &dataList)
{
    QVARIANTMAP_INT_MAP result;
    if (dataList.isEmpty()) return result;

    result = chargingProfileToMapByConnectorId(dataList);

    return result;
}

/**
 * @brief GeneralInterface::chargingProfileMapToList    map转充电配置
 * @param dataMap
 * @return
 */
QList<charging_profiles_detail_info_t> GeneralInterface::chargingProfileMapToList(const QMap<int, QVariant> &dataMap)
{
    QList<charging_profiles_detail_info_t> result;
    if (dataMap.isEmpty()) return result;

    result = chargingProfileMapToListByConnectorId(dataMap);

    return result;
}

/**
 * @brief GeneralInterface::chargingProfileToMapByConnectorId   根据充电配置ID转map
 * @param dataList
 * @return
 */
QMap<int, QVariant> GeneralInterface::chargingProfileToMapByConnectorId(const QList<charging_profiles_detail_info_t> &dataList)
{
    QMap<int, QVariant> result;
    foreach (const auto& data, dataList) {
        auto map = chargingProfileToMapByPurpose(dataList,
                                                 data.connectorId);
        result.insert(data.connectorId, QVariant::fromValue(map));
    }

    return result;
}

/**
 * @brief GeneralInterface::chargingProfileMapToListByConnectorId   map转充电配置ID
 * @param dataMap
 * @return
 */
QList<charging_profiles_detail_info_t> GeneralInterface::chargingProfileMapToListByConnectorId(const QMap<int, QVariant> &dataMap)
{
    QList<charging_profiles_detail_info_t> result;
    foreach (const auto& data, dataMap) {
        result.append(chargingProfileMapToListByPurpose(data.value<QMap<QString, QVariant>>(), dataMap.key(data)));
    }

    return result;
}

/**
 * @brief GeneralInterface::chargingProfileToMapByPurpose   根据充电配置目的转map
 * @param dataList
 * @param connectorId   充电配置ID
 * @return
 */
QMap<QString, QVariant> GeneralInterface::chargingProfileToMapByPurpose(const QList<charging_profiles_detail_info_t> &dataList,
                                                                        const int &connectorId)
{
    QMap<QString, QVariant> result;
    foreach (const auto& data, dataList) {
        if (data.connectorId == connectorId) {
            auto map = chargingProfileToMapByKind(dataList,
                                                  data.connectorId,
                                                  data.chargingProfilePurpose);
            result.insert(data.chargingProfilePurpose, QVariant::fromValue(map));
        }
    }

    return result;
}

/**
 * @brief GeneralInterface::chargingProfileMapToListByPurpose   map转充电配置目的
 * @param dataMap
 * @param connectorId
 * @return
 */
QList<charging_profiles_detail_info_t> GeneralInterface::chargingProfileMapToListByPurpose(const QMap<QString, QVariant> &dataMap,
                                                                                           const int &connectorId)
{
    QList<charging_profiles_detail_info_t> result;
    foreach (const auto& data, dataMap) {
        result.append(chargingProfileMapToListByKind(data.value<QMap<QString, QVariant>>(),
                                                     connectorId,
                                                     dataMap.key(data)));
    }

    return result;
}

/**
 * @brief GeneralInterface::chargingProfileToMapByKind  根据充电配置类型转map
 * @param dataList
 * @param connectorId
 * @param purpose
 * @return
 */
QMap<QString, QVariant> GeneralInterface::chargingProfileToMapByKind(const QList<charging_profiles_detail_info_t> &dataList,
                                                                     const int &connectorId,
                                                                     const QString &purpose)
{
    QMap<QString, QVariant> result;
    foreach (const auto& data, dataList) {
        if (data.connectorId == connectorId &&
            data.chargingProfilePurpose == purpose) {
                auto map = chargingProfileToMapByRecurrencyKind(dataList,
                                                                data.connectorId,
                                                                data.chargingProfilePurpose,
                                                                data.chargingProfileKind);
                result.insert(data.chargingProfileKind, QVariant::fromValue(map));
        }
    }

    return result;
}

/**
 * @brief GeneralInterface::chargingProfileMapToListByKind  map转充电配置类型
 * @param dataMap
 * @param connectorId
 * @param purpose
 * @return
 */
QList<charging_profiles_detail_info_t> GeneralInterface::chargingProfileMapToListByKind(const QMap<QString, QVariant> &dataMap,
                                                                                        const int &connectorId,
                                                                                        const QString &purpose)
{
    QList<charging_profiles_detail_info_t> result;
    foreach (const auto& data, dataMap) {
        result.append(chargingProfileMapToListRecurrencyKind(data.value<QMap<QString, QVariant>>(),
                                                             connectorId,
                                                             purpose,
                                                             dataMap.key(data)));
    }

    return result;
}

/** 
 * @brief GeneralInterface::chargingProfileToMapByRecurrencyKind    根据充电配置周期转map
 * @param dataList
 * @param connectorId
 * @param purpose
 * @param kind
 * @return
 */
QMap<QString, QVariant> GeneralInterface::chargingProfileToMapByRecurrencyKind(const QList<charging_profiles_detail_info_t> &dataList,
                                                                               const int &connectorId,
                                                                               const QString &purpose,
                                                                               const QString &kind)
{
    QMap<QString, QVariant> result;
    foreach (const auto& data, dataList) {
        if (data.connectorId == connectorId &&
            data.chargingProfilePurpose == purpose &&
            data.chargingProfileKind == kind) {
                auto variantList = chargingProfileToMapByRecurrencyKind(dataList,
                                                                    data.connectorId,
                                                                    data.chargingProfilePurpose,
                                                                    data.chargingProfileKind,
                                                                    data.recurrencyKind);
                result.insert(data.recurrencyKind, QVariant::fromValue(variantList));
        }
    }

    return result;
}

/**
 * @brief GeneralInterface::chargingProfileMapToListRecurrencyKind  map转充电配置周期
 * @param dataMap
 * @param connectorId
 * @param purpose
 * @param kind
 * @return
 */
QList<charging_profiles_detail_info_t> GeneralInterface::chargingProfileMapToListRecurrencyKind(const QMap<QString, QVariant> &dataMap,
                                                                                                const int &connectorId,
                                                                                                const QString &purpose,
                                                                                                const QString &kind)
{
    QList<charging_profiles_detail_info_t> result;
    foreach (const auto& data, dataMap) {
        result.append(chargingProfileMapToListRecurrencyKind(data.value<QMap<int, QVariant>>(),
                                                             connectorId,
                                                             purpose,
                                                             kind,
                                                             dataMap.key(data)));
    }

    return result;
}

/**
 * @brief GeneralInterface::chargingProfileToMapByRecurrencyKind    根据充电配置栈级转map
 * @param dataList
 * @param connectorId
 * @param purpose
 * @param kind
 * @param recurrencyKind
 * @return
 */
QMap<int, QVariant> GeneralInterface::chargingProfileToMapByRecurrencyKind(const QList<charging_profiles_detail_info_t> &dataList,
                                                                    const int &connectorId,
                                                                    const QString &purpose,
                                                                    const QString &kind,
                                                                    const QString &recurrencyKind)
{
    QMap<int, QVariant> result;
    foreach (const auto& data, dataList) {
        if (data.connectorId == connectorId &&
            data.chargingProfilePurpose == purpose &&
            data.chargingProfileKind == kind &&
            data.recurrencyKind == recurrencyKind) {
            auto map = chargingProfileToMapByStackLevel(dataList,
                                                        data.connectorId,
                                                        data.chargingProfilePurpose,
                                                        data.chargingProfileKind,
                                                        data.recurrencyKind,
                                                        data.stackLevel);
            result.insert(data.stackLevel, QVariant::fromValue(map));
        }
    }

    return result;
}

/**
 * @brief GeneralInterface::chargingProfileMapToListRecurrencyKind  map转充电配置栈级
 * @param dataMap
 * @param connectorId
 * @param purpose
 * @param kind
 * @param recurrencyKind
 * @return
 */
QList<charging_profiles_detail_info_t> GeneralInterface::chargingProfileMapToListRecurrencyKind(const QMap<int, QVariant> &dataMap,
                                                                                                const int &connectorId,
                                                                                                const QString &purpose,
                                                                                                const QString &kind,
                                                                                                const QString &recurrencyKind)
{
    QList<charging_profiles_detail_info_t> result;
    foreach (const auto& data, dataMap) {
        result.append(chargingProfileMapToListByStackLevel(data.value<QVariantList>(),
                                                           connectorId,
                                                           purpose,
                                                           kind,
                                                           recurrencyKind,
                                                           dataMap.key(data)));
    }

    return result;
}

/**
 * @brief GeneralInterface::chargingProfileToMapByStackLevel    根据充电配置栈级转map
 * @param dataList
 * @param connectorId
 * @param purpose
 * @param kind
 * @param recurrencyKind
 * @param stackLevel
 * @return
 */
QVariantList GeneralInterface::chargingProfileToMapByStackLevel(const QList<charging_profiles_detail_info_t> &dataList, const int &connectorId, const QString &purpose, const QString &kind, const QString &recurrencyKind, const int &stackLevel)
{
    QVariantList result;
    foreach (const auto& data, dataList) {
        if (data.connectorId == connectorId &&
            data.chargingProfilePurpose == purpose &&
            data.chargingProfileKind == kind &&
            data.recurrencyKind == recurrencyKind &&
            data.stackLevel == stackLevel) {

            result.append(QVariant::fromValue(data));
        }
    }

    return result;
}

/**
 * @brief GeneralInterface::chargingProfileMapToListByStackLevel    map转充电配置栈级
 * @param dataMap
 * @param connectorId
 * @param purpose
 * @param kind
 * @param recurrencyKind
 * @param stackLevel
 * @return
 */
QList<charging_profiles_detail_info_t> GeneralInterface::chargingProfileMapToListByStackLevel(const QVariantList &dataMap, const int &connectorId, const QString &purpose, const QString &kind, const QString &recurrencyKind, const int &stackLevel)
{
    QList<charging_profiles_detail_info_t> result;
    foreach (const auto& data, dataMap) {
        if (data.value<charging_profiles_detail_info_t>().connectorId == connectorId &&
            data.value<charging_profiles_detail_info_t>().stackLevel == stackLevel &&
            data.value<charging_profiles_detail_info_t>().chargingProfilePurpose == purpose &&
            data.value<charging_profiles_detail_info_t>().chargingProfileKind == kind &&
            data.value<charging_profiles_detail_info_t>().recurrencyKind == recurrencyKind) {
            result.append(data.value<charging_profiles_detail_info_t>());
        }
    }

    return result;
}

/**
 * @brief   GeneralInterface::getMaxElecment  获取最大值
 * @param   list
 * @return  list为空返回-1，否则返回最大值
 */
int GeneralInterface::getMaxElecment(const QList<int> &list)
{
    int result = -1;
    if (list.isEmpty()) return result;
    for (const auto& num : list) {
        if (num > result) result = num;
    }

    return result;
}

uint32_t GeneralInterface::getMaxElecment(const QList<uint32_t> &list)
{
    uint32_t result = 0;
    if (list.isEmpty()) return result;
    for (const auto& num : list) {
        if (num > result) result = num;
    }

    return result;
}

uint32_t GeneralInterface::getMaxErrorCode(const ERROR_NOTE_LIST &info)
{
    QList<uint32_t> error_code_list;
    foreach (const auto& data, info) {
        error_code_list.append(data.error_code);
    }

    return getMaxElecment(error_code_list);
}

/**
 * @brief   GeneralInterface::getCurrentDate  获取当前时间
 * @param   seconds   秒数
 * @return  返回“HH:mm:ss”的字符串
 */
QString GeneralInterface::getCurrentDate(const int &seconds)
{
    QDate date = QDate::currentDate();
    QTime time = QTime(0, 0, 0).addSecs(seconds);
    QDateTime dt(date, time);
    return dt.toString("HH:mm:ss");
}

/**
 * @brief   GeneralInterface::getCurrentDate  获取当前时间
 * @param   time  时间字符串
 * @return  返回秒数
 */
int GeneralInterface::getCurrentDate(const QString &time)
{
    QTime dt = QTime::fromString(time, "HH:mm:ss");
    return QTime(0, 0, 0).secsTo(dt);
}

/**
 * @brief   GeneralInterface::getCurrentDateOfWeek    获取当前周时间
 * @param   startTime   开始时间
 * @param   seconds     秒数
 * @return  返回“HH:mm:ss”的字符串
 */
QString GeneralInterface::getCurrentDateOfWeek(const QString &startTime, const int &seconds)
{
    QDateTime dt = QDateTime::fromString(startTime, Qt::ISODate);
    dt.setTimeSpec(Qt::UTC);
    dt = dt.addSecs(seconds);
    return dt.toString("HH:mm:ss");
}

/**
 * @brief   GeneralInterface::getCurrentDateSecondOfWeek  获取当前周时间
 * @param   startTime   开始时间
 * @param   seconds     秒数
 * @return  返回秒数
 */
int GeneralInterface::getCurrentDateSecondOfWeek(const QString &startTime, const int &seconds)
{
    // 1. 解析开始时间
    QDateTime startDt = QDateTime::fromString(startTime, Qt::ISODate);
    startDt.setTimeSpec(Qt::UTC);

    // 2. 计算目标时间
    QDateTime targetDt = startDt.addSecs(seconds);

    // 3. 获取当天00:00:00到目标时间的秒数
    int secondsOfDay = QTime(0, 0, 0).secsTo(targetDt.time());
    return secondsOfDay;
}

/**
 * @brief   GeneralInterface::getCurrentDateOfWeek    获取当前周时间
 * @param   startTime   开始时间
 * @param   seconds     秒数
 * @param   dayOfWeek   周几
 * @return  返回秒数
 */
int GeneralInterface::getCurrentDateOfWeek(const QString &startTime, const int &seconds, const int &dayOfWeek)
{
    // 1. 解析开始时间
    QDateTime startDt = QDateTime::fromString(startTime, Qt::ISODate);
    startDt.setTimeSpec(Qt::UTC);

    // 2. 获取开始时间所在周的周一
    QDate startDate = startDt.date();
    int startDayOfWeek = startDate.dayOfWeek(); // 1=周一
    QDate monday = startDate.addDays(1 - startDayOfWeek);

    // 3. 目标日期 = 本周的 dayOfWeek
    QDate targetDate = monday.addDays(dayOfWeek - 1);

    // 4. 用秒数构造 QTime
    QTime targetTime = QTime(0, 0, 0).addSecs(seconds);

    // 5. 构造目标 QDateTime
    QDateTime targetDt(targetDate, targetTime, Qt::UTC);

    // 6. 计算秒数差
    qint64 secondsDiff = startDt.secsTo(targetDt);
    return static_cast<int>(secondsDiff);
}

/**
 * @brief   GeneralInterface::getCurrentDateOfWeek    获取当前周时间
 * @param   startTime 开始时间
 * @param   time      时间字符串
 * @param   dayOfWeek 周几
 * @return
 */
int GeneralInterface::getCurrentDateOfWeek(const QString &startTime, const QString &time, const int& dayOfWeek)
{
    // 1. 解析开始时间
    QDateTime startDt = QDateTime::fromString(startTime, Qt::ISODate);
    startDt.setTimeSpec(Qt::UTC); // 若有Z，确保为UTC

    // 2. 获取开始时间所在周的周一
    QDate startDate = startDt.date();
    int startDayOfWeek = startDate.dayOfWeek(); // 1=周一
    QDate monday = startDate.addDays(1 - startDayOfWeek);

    // 3. 目标日期 = 本周的 dayOfWeek
    QDate targetDate = monday.addDays(dayOfWeek - 1);

    // 4. 解析当天时间
    QTime targetTime = QTime::fromString(time, "HH:mm:ss");

    // 5. 构造目标 QDateTime
    QDateTime targetDt(targetDate, targetTime, Qt::UTC);

    // 6. 计算秒数差
    qint64 secondsDiff = startDt.secsTo(targetDt);
    return static_cast<int>(secondsDiff);
}

/**
 * @brief   GeneralInterface::getDayOfWeek    获取当前周几
 * @param   time  时间字符串
 * @return  1=周一、2=周二、3=周三、4=周四、5=周五、6=周六、7=周日
 */
int GeneralInterface::getDayOfWeek(const QString &time)
{
    QDateTime dt = QDateTime::fromString(time, Qt::ISODate);
    dt.setTimeSpec(Qt::UTC); // 明确为UTC时间
    QDate date = dt.date();
    return date.dayOfWeek();
}

/**
 * @brief GeneralInterface::sortByStartPeriod   按开始时间排序
 * @param list  
 */
void GeneralInterface::sortByStartPeriod(QList<charging_schedule_period_info_t> &list)
{
    std::sort(list.begin(), list.end(), [](const charging_schedule_period_info_t &a, const charging_schedule_period_info_t &b) {
        return a.startPeriod < b.startPeriod;
    });
}

/**
 * @brief GeneralInterface::sortByStackLevel    按优先级排序
 * @param list
 */
void GeneralInterface::sortByStackLevel(QList<charging_profiles_detail_info_t> &list)
{
    std::sort(list.begin(), list.end(), [](const charging_profiles_detail_info_t &a, const charging_profiles_detail_info_t &b) {
        return a.stackLevel > b.stackLevel;
    });
}

/**
 * @brief   GeneralInterface::getMaxChargingProfileId 获取最大充电配置ID
 * @param   list
 * @return  list为空返回-1，否则返回最大值
 */
int GeneralInterface::getMaxChargingProfileId(QList<charging_profiles_detail_info_t> &list)
{
    QList<int> chargingProfileIdList;
    foreach (const auto& data, list) {
        chargingProfileIdList.append(data.chargingProfileId);
    }

    return getMaxElecment(chargingProfileIdList);
}

/**
 * @brief GeneralInterface::getVersion 获取版本号
 * @param appName
 * @return
 * HW_NAME: 硬件版本号
 * CCU_NAME: CCU版本号
 * TCU_NAME: TCU版本号
 * PCU_NAME: PCU版本号
 */
QString GeneralInterface::getVersion(const QString &appName)
{
    QString version;
    if (appName == AppName::HW_NAME) {
        version = VersionManager::getHardwareVersion();
    } else if (appName == AppName::CCU_NAME ||
               appName == AppName::TCU_NAME ||
               appName == AppName::PCU_NAME) {
        AppVersionInfo info = VersionManager::getAppVersion(appName);
        if (info.success) {
            version = QString("V%1.%2.%3").arg(info.major).arg(info.minor).arg(info.build);
        }
    }
    return version;
}

/*
QPixmap GeneralInterface::generateQRCode(const QString &text, int size)
{
    QRcode *qr = QRcode_encodeString(text.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1);
    if (!qr) return QPixmap();

    // 计算缩放比例（二维码实际大小可能小于请求的 size）
    int qrSize = qr->width > 0 ? qr->width : 1;
    int scale = size / qrSize;
    if (scale < 1) scale = 1;

    // 创建 QImage 并绘制二维码
    QImage image(qrSize * scale, qrSize * scale, QImage::Format_RGB32);
    image.fill(Qt::white);

    QPainter painter(&image);
    painter.setPen(Qt::black);
    for (int y = 0; y < qrSize; y++) {
        for (int x = 0; x < qrSize; x++) {
            if (qr->data[y * qrSize + x] & 0x01) {
                painter.fillRect(x * scale, y * scale, scale, scale, Qt::black);
            }
        }
    }
    QRcode_free(qr);

    return QPixmap::fromImage(image);
}*/

/**
 * @brief GeneralInterface::formatMillisecondDifference 格式化毫秒差
 * @param ms1
 * @param ms2
 * @return  
 */
QString GeneralInterface::formatMillisecondDifference(qint64 ms1, qint64 ms2)
{
    qint64 diffMs = qAbs(ms1 - ms2); // 取绝对值

    QTime time(0, 0);
    time = time.addMSecs(diffMs);

    return time.toString("HH:mm:ss");
}

/**
 * @brief GeneralInterface::makeLabelJump   使标签跳一下
 * @param label 
 */
void GeneralInterface::makeLabelJump(QLabel* label) {
    // 创建动画组
    QParallelAnimationGroup *group = new QParallelAnimationGroup(label);

    // 位置动画
    QPropertyAnimation *posAnim = new QPropertyAnimation(label, "pos", group);
    posAnim->setDuration(800);
    posAnim->setEasingCurve(QEasingCurve::OutQuad);
    posAnim->setKeyValueAt(0, label->pos());
    posAnim->setKeyValueAt(0.5, label->pos() + QPoint(0, -80));
    posAnim->setKeyValueAt(1, label->pos());

    // 缩放动画
    QPropertyAnimation *scaleAnim = new QPropertyAnimation(label, "geometry", group);
    scaleAnim->setDuration(800);
    scaleAnim->setEasingCurve(QEasingCurve::OutQuad);
    QRect startRect = label->geometry();
    scaleAnim->setKeyValueAt(0, startRect);
    scaleAnim->setKeyValueAt(0.5, QRect(
                                      startRect.x() - 10,
                                      startRect.y() - 80,
                                      startRect.width() + 20,
                                      startRect.height() + 20
                                      ));
    scaleAnim->setKeyValueAt(1, startRect);

    // 启动动画
    group->start(QAbstractAnimation::DeleteWhenStopped);
}

/**
 * @brief GeneralInterface::encodeAuthInfo  编码认证信息
 * @param data  
 * @return  
 */
QByteArray GeneralInterface::encodeAuthInfo(const GUN_AUTH &data)
{
    QByteArray result;
    result.append(encodeValue<const uint32_t>(data.GUNID, 1));
    result.append(0x81);
    result.append(sizeof(data.EMID));
    result.append(QByteArray(reinterpret_cast<const char*>(&data.EMID), sizeof(data.EMID)));
    result.append(encodeValue<const uint32_t>(data.requestKWs, 1));
    return result;
}

/**
 * @brief GeneralInterface::getGunIconUrl    获取枪口图标
 * @param type      枪口类型
 * @param isError   是否错误
 * @return  返回枪口图标URL
 */
QString GeneralInterface::getGunIconUrl(const uint8_t &type, bool isError)
{
    QString icon_url = "";
    switch (type) {
    case GUNTYPE_NACS:
        icon_url = QString(":/icons/%1.png").arg("nacs" + QString("%1").arg(isError ? "_faild" : ""));
        break;
    case GUNTYPE_CCS1:
        icon_url = QString(":/icons/%1.png").arg("ccs1" + QString("%1").arg(isError ? "_faild" : ""));
        break;
    case GUNTYPE_CCS2:
        icon_url = QString(":/icons/%1.png").arg("ccs2" + QString("%1").arg(isError ? "_faild" : ""));
        break;
    case GUNTYPE_CHADEMO:
        icon_url = QString(":/icons/%1.png").arg("chademo" + QString("%1").arg(isError ? "_faild" : ""));
        break;
    case GUNTYPE_GBDC:
        icon_url = QString(":/icons/%1.png").arg("gbdc" + QString("%1").arg(isError ? "_faild" : ""));
        break;
    default:
        break;
    }

    return icon_url;
}

/**
 * @brief GeneralInterface::isError 判断是否有错误
 * @param error_list    错误列表
 * @return  错误返回true，否则返回false
 */
bool GeneralInterface::isError(const QList<uint32_t> &error_list)
{
    return std::any_of(error_list.begin(), error_list.end(),
                       [](uint32_t value) { return (value > CHARGE_GUN_ERROR_MAX_INDEX); });
}

/**
 * @brief GeneralInterface::getMaxElement   获取最大值
 * @param state_list     状态列表
 * @return  
 */
uint8_t GeneralInterface::getMaxElement(const QList<uint32_t> &state_list)
{
    if (state_list.isEmpty()) {
        return 0; // 或者抛出异常
    }

    auto it = std::max_element(state_list.begin(), state_list.end());
    return *it;
}

/**
 * @brief GeneralInterface::addRotationAnimation    添加旋转动画
 * @param label 
 */
void GeneralInterface::addRotationAnimation(QLabel *label)
{
    // 创建图形场景和代理
    QGraphicsScene *scene = new QGraphicsScene(label->parentWidget());
    QGraphicsProxyWidget *proxy = scene->addWidget(label);

    // 设置旋转中心为标签中心
    proxy->setTransformOriginPoint(proxy->boundingRect().center());

    // 创建旋转动画
    QPropertyAnimation *animation = new QPropertyAnimation(label, "rotation");
    animation->setDuration(2000);  // 动画持续时间(毫秒)
    animation->setStartValue(0);   // 起始角度
    animation->setEndValue(360);   // 结束角度(360度)
    animation->setLoopCount(-1);   // 无限循环
    animation->start();
}

/**
 * @brief GeneralInterface::getMaxElementWithQMax   获取最大值
 * @param list  
 * @return  
 */
uint8_t GeneralInterface::getMaxElementWithQMax(const QList<uint8_t> &list)
{
    if (list.isEmpty()) {
        return 0;
    }

    int max = list.first();
    for (int num : list) {
        max = qMax(max, num);
    }
    return max;
}

/**
 * @brief GeneralInterface::getTips 获取提示信息
 * @param state 状态码
 * @return  
 */
QString GeneralInterface::getTips(const int &state)
{
    switch (state) {
    case CHARGE_GUN_AVAILABLE:      return tr("Please Plug in");
    case AUTHORIZATION_QR:          return tr("Please scan the QR code");
    case AUTHORIZATION_ID_CARD:     return tr("Please swipe the card");
    case AUTHORIZATION_QR_ID_CARD:  return tr("Please swipe the card or scan the QR code");
    case WAITING_NO_ID_CARD:        return tr("Do not swipe card");
    case WAITING_NO_ID_CARD_QR:     return tr("Do not swipe card; QR code scan works normally");
    case WAITING_STANDBY:           return tr("waiting");
    case AUTHORIZING_ONLINE:        return tr("Authorizing online");
    case RETRY:                     return tr("Retry");
    case TIMEOUT:                   return tr("Timeout");
    case RETRY_OR_RETURN_GUN:       return tr("Please try again or return the connector");
    case SCAN_QR_OR_RETURN_GUN:     return tr("Scan the QR code or return the connector");
    case FAILED:                    return tr("Failed");
    case CARD_AUTHORIZATION_FAILED: return tr("Charging authorization failed");
    case CHANGE_CARD:               return tr("Please use another card or return the connector");
    case BALANCE_NO_START:          return tr("Balance:$0x01, insufficient to start charging");
    case TOP_UP_RETRY:              return tr("Please top up the funds then try again");
    case PREPARE_HANDSHAKING:       return tr("Preparing Handshaking");
    case HANDSHAKING:               return tr("Handshaking");
    case CONFIGUING:                return tr("Configuring");
    case START_CHARGING:            return tr("Start Charging");
    case STARTUP_FAILED:            return tr("Startup Failed");
    case UNPLUG_RETRY_OR_CHANGE:    return tr("Please try unplug the connector and reconnect it to the vehicle or use another connector");
    case STOP_CHARGING:             return tr("STOP");
    case TIME_REMAINING:            return tr("mins remaining");
    case RETURN_GUN:                return tr("Please return the connector");
    case RESTART_CHARGING:          return tr("Restart");
    case CHARGING_STOP_ABNORMAL:    return tr("");
    case UNAVAILABLE:               return tr("Unavailable");
    case CHARGE_GUN_UNAVILABLE:     return tr("This connector is currently unavailable. Please use another one.");
    case OUT_OF_SERVICE:            return tr("This charging station is in out-of-service hours and unable to provide charging services.");
    case MAX_POWER_LIMIT:           return tr("This charging station has reached its maximum power limit and cannot be activated for charging.");
    default:                        return tr("");
    }
}

/**
 * @brief GeneralInterface::isCrossTime 判断时间是否交叉
 * @param start     开始时间
 * @param end       结束时间
 * @return  交叉返回 true，否则返回 false
 */
bool GeneralInterface::isCrossTime(const uint32_t &start, const uint32_t &end)
{
    return start > end;
}

/**
 * @brief GeneralInterface::getAuthResult   获取授权结果
 * @param cardId    卡号
 * @return  卡号存在且状态为无效且过期则返回 0，否则返回 1
 */
int GeneralInterface::getAuthResult(const QByteArray &cardId)
{
    auto auth_list = GLOBALS->getValue(Global::Keys::AUTH_LIST).value<AUTH_LIST>();
    auto cfg_key = GLOBALS->getValue(Global::Keys::CFG_KEY).value<CONFIG_KEY_INFO>();

    int result = 1;
    if (cfg_key.CoreProfile.AuthorizationCacheEnabled)  {               // auth list cache
        foreach (const auto& value, auth_list.authorizationCache) {
            if (cardId.data() == value.idTag &&
                value.status == "Invalid" &&
                isTimeout(value.expiryDate)) {
                result = 0;
            }
        }
    }

    if (cfg_key.LocalAuthListManagementProfile.LocalAuthListEnabled) {  // local auth list
        foreach (const auto& value, auth_list.localAuthorizationList) {
            if (cardId.data() == value.idTag &&
                value.status == "Invalid" &&
                isTimeout(value.expiryDate)) {
                result = 0;
            }
        }
    }

    return result;
}

/**
 * @brief GeneralInterface::isTimeout   判断时间是否过期
 * @param date   时间字符串
 * @return  过期返回 true，否则返回 false
 */
bool GeneralInterface::isTimeout(const QString &date)
{
    // 将字符串转换为 QDateTime
    QDateTime targetTime = QDateTime::fromString(date, Qt::ISODate);

    if (!targetTime.isValid()) {
        return false;
    }

    // 转换为UTC时间以确保比较准确
    targetTime = targetTime.toUTC();

    QDateTime cur_time = QDateTime::currentDateTimeUtc();

    return targetTime < cur_time;
}
