#include "rollback.h"
#include "fmglobal.h"
#include <QSqlQuery>
#include <QEventLoop>
#include <QJsonDocument>
#include <QTimer>
#include <QSettings>
#include <QJsonObject>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QMap>
#include <QSqlError>
#include "tools.h"
#include "QsLog.h"
#include "cretopt.h"
#include "fmnetwork.h"
#include <QtConcurrent>

QMap<QString, QString> RollBack::s_rollorder;
QMutex RollBack::s_rollorder_lock;

RollBack::RollBack(QObject *parent) : QThread(parent)
{
    _posType = (POSType)_setting.GetValue(CONFIG_ALL_PARTNER, SPCC).toInt();
}

RollBack::~RollBack()
{
    requestInterruption();
    wait();

//    if(_db != NULL)
//    {
//        delete _db;
//        _db = NULL;
//    }

}

void RollBack::RollWiteQuery(QSqlDatabase &_db, QSqlQuery &query)
{
    while(query.next())
    {
        QString parnetid = query.value(0).toString();
        QString content = query.value(1).toString();

        QJsonDocument jsonDocument = QJsonDocument::fromJson(content.toUtf8());

        if( jsonDocument.isNull() )
        {
            QString sql = QString("delete from orderlist where orderid='%1'").arg(parnetid);
            QLOG_ERROR() << sql;
            query.exec(sql);
        }

        QJsonObject json = jsonDocument.object();

        json[JSON_KEY_REQTYPE] = 3;
        json[JSON_KEY_VER] = DEFAULT_JSON_VER_VALUE;

        QString iv = json[JSON_KEY_RPARTNERID].toString() + json[JSON_KEY_RSTOREID].toString() + json[JSON_KEY_RSTATIONID].toString();

        if(!CretOperate::GetSign(json, iv))
        {
            QLOG_ERROR() << "rollback : " << "get sign error";
            continue;
        }

        QLOG_INFO() << "rollback : " << json;


        QByteArray array;

        QString error;

        if(_posType == SPCC) {
            if(FMNetWork::RequestToOLTP(json, array, error, 20))
            {
                QString sql = QString("delete from orderlist where orderid='%1'").arg(parnetid);
                QLOG_INFO() << sql;
                if(!query.exec(sql))
                    QLOG_ERROR() << query.lastError() << query.lastError().text();

            }
        } else {
            QString url = _setting.GetValue(VALUE_URL, "").toString();

            QByteArray data = QJsonDocument(json).toJson(QJsonDocument::Compact);
            if(FMNetWork::HttpPost(url, array, data, "application/json;charset=utf-8","application/json", error, 12))
            {
                QString sql = QString("delete from orderlist where orderid='%1'").arg(parnetid);
                QLOG_ERROR() << sql;
                query.exec(sql);
            }
        }

        QLOG_WARN() << "rollback : " << "rollback resulte " << QThread::currentThreadId() << ":" << array;

    }
}

void RollBack::run()
{
    QString path;
    ToolS::GetPath(path);

    while(!isInterruptionRequested())
    {

        int timeout = _setting.GetValue(VALUE_TIMEOUT, 30).toInt();

        do
        {
            QSqlDatabase _db = QSqlDatabase::addDatabase("QSQLITE", QString("backup"));
            _db.setDatabaseName(path + DB_ORDER);
            _db.open();

            QSqlQuery query(_db);
            InsertRollOrder(query);
            query.clear();

//            QLOG_WARN() << "rollback : " << "find sql : " << "select * from orderlist";

            bool flag = query.exec("select * from orderlist");

            if(!flag)
                QLOG_WARN() << "rollback : " << query.lastError();


            RollWiteQuery(_db, query);

            _db.close();

        }while(0);

        QEventLoop loop;
        QTimer timer;
        connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
        timer.start(timeout*1000);

        loop.exec();
    }
}

void RollBack::InsertRollOrder(QSqlQuery &query)
{
    QMap<QString , QString> tmporder = s_rollorder;

    QMap<QString,QString>::Iterator  it;

    QLOG_INFO() << "rollback : " << "roll order map " << tmporder;

    for(it = tmporder.begin(); it != tmporder.end(); ++it)
    {
        if(!it.key().isEmpty())
        {
           QString sql = QString("insert into %1 ( 'orderid', 'content') values ('%2', '%3')").arg(DB_TABLE_NAME).arg(it.key()).arg(it.value());

           QLOG_INFO() << "rollback : " << "insert sql " << sql;

           if(!query.exec(sql))
           {
               QLOG_ERROR() << "rollback : " << query.lastError() << query.lastError().text();
           }
           else
           {
                s_rollorder_lock.lock();
                s_rollorder.remove(it.key());
                s_rollorder_lock.unlock();
           }
        }
        else
        {
            QLOG_ERROR() << "rollback : " << "rollorder error " << it.key() << it.value();
        }
    }

    s_rollorder_lock.lock();
    if(s_rollorder.size() > 300)
    {
        QLOG_WARN() << "rollback : " << "map size big clean : " << s_rollorder.size();
        s_rollorder.clear();
    }
    s_rollorder_lock.unlock();

}

void RollBack::SetRollOrder(QString orderid, QString request)
{
    QLOG_INFO() << "rollback : "<< "new roll order " << orderid << request;
    s_rollorder_lock.lock();
    s_rollorder.insert(orderid, request);
    s_rollorder_lock.unlock();
}
