#include "NFCReaderWorker.h"
#include "M4255NFCHelper.h"

#include "LoggerHelper.h"
#include "ConfigManager.h"
#include <QDebug>

NFCReaderWorker::NFCReaderWorker(QObject *parent)
    : QObject(parent)
{
    m_tcu_cfg = ConfigManager::instance()->tcu_cfg();
}

NFCReaderWorker::~NFCReaderWorker()
{
    // m_nfcReader will be deleted automatically due to parent-child relationship
}

void NFCReaderWorker::doWork(const QString& portName, int gunId, int timeout)
{
    m_activeReader = std::make_unique<M4255NFCHelper>();
    if (m_activeReader->isPortOpen()) {
        LOG_INFO(QString("Gun %1: NFCReaderWorker is busy, another operation is in progress.").arg(gunId));
        emit resultReady(AuthError::WAITING_FOR_OTHER_INSTANCE, "");
        return;
    }

    LOG_INFO(QString("Gun %1: NFCReaderWorker starts authentication in thread...").arg(QString::number(gunId)));
    if (m_activeReader->init(portName)) {
        LOG_ERROR(QString("Gun %1: NFCReaderWorker init failed.").arg(QString::number(gunId)));
        emit resultReady(AuthError::INIT_FAILED, "");
        return;
    }
    LOG_INFO(QString("Gun %1: NFC device initialization completed.").arg(QString::number(gunId)));

    if (m_activeReader->setBeep(1) != 0) {
        m_activeReader->closePort();
        emit resultReady(AuthError::INIT_FAILED, "");
        return;
    }

    if (m_activeReader->setReadOnce(M4255_READ_ONLYONCE) != 0) {
        m_activeReader->closePort();
        emit resultReady(AuthError::INIT_FAILED, "");
        return;
    }

    if (m_activeReader->setWorkMode(M4255_AUTO_READ_CARDID) != 0) {
        m_activeReader->closePort();
        emit resultReady(AuthError::INIT_FAILED, "");
        return;
    }

    QByteArray cardId;
    LOG_INFO(QString("Gun %1: NFC device: Start waiting to read the card ID...").arg(QString::number(gunId)));
    int ret = m_activeReader->waitReadCardId(cardId, timeout);
    if (ret != 0 || cardId.isEmpty()) {
        m_activeReader->closePort();
        LOG_INFO(QString("Gun %1: NFC device: Read card id timeout or failed.").arg(QString::number(gunId)));
        emit resultReady(AuthError::READ_CARD_FAILED, "");
        return;
    }

    m_activeReader->setWorkMode(M4255_CMD_MODE);
    m_activeReader->forceBeep(0);
    m_activeReader->closePort();

    QString cardId_str = QString("NFCA") + cardId.toHex().toUpper();
    LOG_INFO(QString("Gun %1: NFC device: Card ID: %2").arg(QString::number(gunId), cardId_str));

    emit resultReady(AuthError::SUCCESS, cardId_str);
}

void NFCReaderWorker::doReadCard(charging_control_info_t& data)
{
    m_activeReader = std::make_unique<M4255NFCHelper>();
    if (m_activeReader->isPortOpen()) {
        LOG_INFO(QString("Gun %1: NFCReaderWorker is busy, another operation is in progress.").arg(data.gunID));
        data.nfcExecResult = AuthError::WAITING_FOR_OTHER_INSTANCE;
        emit execResultReady(data);
        return;
    }

    LOG_INFO(QString("Gun %1: NFCReaderWorker starts authentication in thread...").arg(QString::number(data.gunID)));
    if (m_activeReader->init(m_tcu_cfg.rs485_port_name)) {
        LOG_ERROR(QString("Gun %1: NFCReaderWorker init failed.").arg(QString::number(data.gunID)));
        data.nfcExecResult = AuthError::INIT_FAILED;
        emit execResultReady(data);
        return;
    }
    LOG_INFO(QString("Gun %1: NFC device initialization completed.").arg(QString::number(data.gunID)));

    if (m_activeReader->setBeep(1) != 0) {
        m_activeReader->closePort();
        data.nfcExecResult = AuthError::INIT_FAILED;
        emit execResultReady(data);
        return;
    }

    if (m_activeReader->setReadOnce(M4255_READ_ONLYONCE) != 0) {
        m_activeReader->closePort();
        data.nfcExecResult = AuthError::INIT_FAILED;
        emit execResultReady(data);
        return;
    }

    if (m_activeReader->setWorkMode(M4255_AUTO_READ_CARDID) != 0) {
        m_activeReader->closePort();
        data.nfcExecResult = AuthError::INIT_FAILED;
        emit execResultReady(data);
        return;
    }

    QByteArray cardId;
    LOG_INFO(QString("Gun %1: NFC device: Start waiting to read the card ID...").arg(QString::number(data.gunID)));
    int ret = m_activeReader->waitReadCardId(cardId, (m_tcu_cfg.time_out.auth_form_wait_time - 1) * 1000);
    if (ret != 0 || cardId.isEmpty()) {
        m_activeReader->closePort();
        LOG_INFO(QString("Gun %1: NFC device: Read card id timeout or failed.").arg(QString::number(data.gunID)));
        data.nfcExecResult = AuthError::READ_CARD_FAILED;
        emit execResultReady(data);
        return;
    }

    m_activeReader->setWorkMode(M4255_CMD_MODE);
    m_activeReader->forceBeep(0);
    m_activeReader->closePort();

    data.cardID = QString("NFCA") + cardId.toHex().toUpper();
    LOG_INFO(QString("Gun %1: NFC device: Card ID: %2").arg(QString::number(data.gunID), data.cardID));
    data.nfcExecResult = AuthError::SUCCESS;
    emit execResultReady(data);
}

void NFCReaderWorker::closePort()
{
    if (m_activeReader) {
        m_activeReader->closePort();
    }
} 
