#include "qtRedisClient.h"
#include "QsLog.h"
#include "DTools/configManger.h"

QtRedisClient::QtRedisClient()
{
    QLOG_INFO()<<"[<<<<---QtRedisClient:: ConStructure Redis Begin --->>>>]";
    initRedisClient();
    m_redisIp = ConfigManger::GetInstance().GetRedisIpConfig();
    // m_redisPassword = ConfigManger::GetInstance().GetRedisPasswordConfig();
    m_RedisConnectCnf.setHost(m_redisIp.length()? m_redisIp : "127.0.0.1");
    m_RedisConnectCnf.setPort(6379);
    m_pRedisConnectOperat = new RedisClient::Connection(m_RedisConnectCnf);
    if ( !m_pRedisConnectOperat ) {
        QLOG_ERROR()<<"[<<<<---QtRedisClient:: ConStructure QtRedisClient m_pRedisConnectOperat New Failed--->>>>]";
    } else {
        QLOG_INFO()<<"[<<<<---QtRedisClient:: ConStructure QtRedisClient m_pRedisConnectOperat New Success--->>>>]";
    }
}


QtRedisClient &QtRedisClient::getInstance()
{
    static QtRedisClient qtRedisClient;
    return qtRedisClient;
}


bool QtRedisClient::initQtRedisClient(){
    bool initRedisRet = false;
    if ( !m_pRedisConnectOperat ) {
        QLOG_ERROR()<<"[<<<<---QtRedisClient::initQtRedisClient  m_pRedisConnectOperat  is  NULL, Will Retry Connect Redis--->>>>]";
        m_RedisConnectCnf.setHost(m_redisIp.length()? m_redisIp : "127.0.0.1");
        m_RedisConnectCnf.setPort(6379);
        try {
            m_pRedisConnectOperat = new RedisClient::Connection( m_RedisConnectCnf );
        } catch ( const RedisClient::Connection::Exception& e  ) {  // SSHSupportException && InvalidModeException;
            QLOG_ERROR()<<"[<<<<---QtRedisClient:: initQtRedisClient  m_pRedisConnectOperat  New Connection Exception: --->>>>]"<<e.what();
            return initRedisRet;
        }
        if (!m_pRedisConnectOperat){
            QLOG_ERROR()<<"[<<<<---QtRedisClient:: initQtRedisClient  m_pRedisConnectOperat  New Connection Still Failed, Wait Next Init*Client --->>>>]";
            return initRedisRet;
        }
    } else {
        QLOG_INFO()<<"[<<<<---QtRedisClient:: initQtRedisClient  m_pRedisConnectOperat  Is Normal , Maybe Connect Redis Success --->>>>]";
    }

    try {
        if ( m_pRedisConnectOperat->isConnected() || m_pRedisConnectOperat->connect() ) {
            QLOG_INFO()<<"[<<<<---QtRedisClient:: initQtRedisClient  Connect Redis Success  --->>>>]";
        } else {
            int retryCount = 0;
            while ( retryCount < 3 ) {
                QLOG_INFO()<<QString("[<<<<---QtRedisClient:: initQtRedisClient  Connect Redis Failed, Sleep 1 s RetryCount: %1 (MaxCount=3), Then Retry Connect... --->>>>]").arg(retryCount+1);
                Sleep(1*1000);
                if ( m_pRedisConnectOperat->connect() )
                    break;
                else {
                    retryCount++;
                    continue;
                }
            }
            if ( retryCount < 3 ) {
                QLOG_INFO()<<"[<<<<---QtRedisClient:: initQtRedisClient  Connect Redis Success  --->>>>]";
            } else {
                QLOG_INFO()<<"[<<<<---QtRedisClient:: initQtRedisClient  Connect Redis Until The Last Failed--->>>>]";
                return initRedisRet;
            }
        }
    } catch ( const RedisClient::Connection::Exception& e ) {
        QLOG_ERROR() << "QtRedisClient::initQtRedisClient Connect Redis Occur Exception:" << e.what();
        return initRedisRet;
    }

    try {
        QList<QByteArray> cmdInfoAllTest;
        cmdInfoAllTest.append("INFO");
        cmdInfoAllTest.append("ALL");
        auto result = m_pRedisConnectOperat->command(cmdInfoAllTest);
        QVariant var = result.result().value();
        QLOG_INFO() << RedisClient::Response::valueToHumanReadString( var );
        /* [](RedisClient::Response r) { const QVariant val = r.value(); QLOG_INFO() << RedisClient::Response::valueToHumanReadString( val ); } */
        // m_pRedisConnectOperat->disconnect(); //避免频繁重复操作，故不 disconnect;
        initRedisRet = true;
    } catch (const RedisClient::Connection::Exception& e) {
        QLOG_ERROR() << "QtRedisClient::initQtRedisClient Cannot Run Command:" << e.what();
    }
    QLOG_INFO()<<"[<<<<---QtRedisClient::initQtRedisClient  initRedisRet:--->>>>]"<< initRedisRet;
    return initRedisRet;
}


bool QtRedisClient::testOrderRedisExist(const QString& orderId){
    bool bOrderExist = false;
    QList<QByteArray> cmdString;
    cmdString.append("GET");
    cmdString.append("ZWY");
    try {
        auto result = m_pRedisConnectOperat->command(cmdString);
        QVariant val = result.result().value();
        // Q_UNUSED(orderId);
        if(val.toString().length()){
            QLOG_INFO() << QString("[<<<<---QtRedisClient::isOrderRedisExist  orderId:%1 Exist ; value:%2:--->>>>]").arg(orderId).arg(val.toString());
        }else{
            QLOG_ERROR() << QString("[<<<<---QtRedisClient::isOrderRedisExist  orderId:%1 Not Exist ; value:%2:--->>>>]").arg(orderId).arg(val.toString());
        }
        bOrderExist = true;
    } catch (const RedisClient::Connection::Exception& e) {
        QLOG_ERROR() << "QtRedisClient::isOrderRedisExist Cannot run command:" << e.what();
    }
    return bOrderExist;
}


bool QtRedisClient::pushOrder2Redis(const OrderObject* orderObj ){
    bool bPushOrderSuc = false;
    QList<QByteArray> cmdString;
    cmdString.append("LPUSH");
    cmdString.append("PmsOrderStatusNotifyList");

    QJsonObject orderStatusObj;
    orderStatusObj.insert("ID",orderObj->id);
    orderStatusObj.insert("STATUS",orderObj->orderStatus);
    QString timeStamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    orderStatusObj.insert("TIMESTAMP",timeStamp);
    orderStatusObj.insert("MAKESTATUS",orderObj->makeStatus);
    orderStatusObj.insert("MAKESOURCE",orderObj->makeSource);
    orderStatusObj.insert("MAKEDEVICEID",orderObj->makeDeviceId);
    orderStatusObj.insert("MAKEDEVICENAME","");
    if ( 7== orderObj->orderType ||  11== orderObj->orderType) {
        orderStatusObj.insert( "ARRIVEAHEAD", orderObj->inAdvanceTakemeal );
    }
    QJsonDocument orderStatusDoc = QJsonDocument(orderStatusObj);
    cmdString.append(orderStatusDoc.toJson());

    QLOG_INFO() << QString("[<<<<---QtRedisClient::pushOrder2Redis  orderId:%1 Begin...... --->>>>]").arg(orderObj->id);

    if ( !m_pRedisConnectOperat ) {
        QLOG_INFO() << QString("[<<<<---QtRedisClient::pushOrder2Redis  orderId:%1  m_pRedisConnectOperat Pointer Is Null, Wait Retry Init --->>>>]").arg(orderObj->id);
        return bPushOrderSuc;
    }
    if ( !m_pRedisConnectOperat->isConnected() ) {
        QLOG_INFO() << QString("[<<<<---QtRedisClient::pushOrder2Redis  orderId:%1  m_pRedisConnectOperat Disconnet, Wait Retry Init --->>>>]").arg(orderObj->id);
        return bPushOrderSuc;
    }

    try {
        auto result = m_pRedisConnectOperat->command(cmdString);
        if ( result.results().size() ) {
            QLOG_INFO() << QString("[<<<<---QtRedisClient::pushOrder2Redis  orderId:%1, Command Run Status:--->>>>]").arg(orderObj->id)
                    <<" Finished: "<< result.isFinished() << " Running: "<<  result.isRunning() << " Paused: "<<  result.isPaused() ;
        } else {
            return bPushOrderSuc;
        }

        QVariant val = result.result().value();
        if ( val.toInt() ) {
            QLOG_INFO() << QString("[<<<<---QtRedisClient::pushOrder2Redis  orderId:%1 ; orderStatus:%2 ; ret:%3 Success--->>>>]").arg(orderObj->id).arg(orderObj->orderStatus).arg(val.toString());
            QLOG_INFO() << QString("[<<<<---QtRedisClient::pushOrder2Redis  orderId:%1 Redis Context:%2--->>>>]").arg(orderObj->id).arg( QString(orderStatusDoc.toJson()) );
            bPushOrderSuc = true;
        } else {
            QLOG_ERROR() << QString("[<<<<---QtRedisClient::pushOrder2Redis  orderId:%1 ; orderStatus:%2 ; val:%3 Failed--->>>>]").arg(orderObj->id).arg(orderObj->orderStatus).arg(val.toString());
        }
    } catch (const RedisClient::Connection::Exception& e) {
        QLOG_ERROR() << "QtRedisClient::isOrderRedisExist Cannot run command:" << e.what();
    }
    return bPushOrderSuc;
}
