#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 <version.h>
#include "QsLog.h"
#include "cretopt.h"
#include "fmnetwork.h"
#include <QtConcurrent>

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

static QString globalDllVersion = QString("%1.%2.%3.%4").arg(VER_MAJOR).arg(VER_MINOR).arg(VER_REVISION).arg(VER_BUILD);

RollBack::RollBack(QObject *parent) : QThread(parent)
{
}

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

void RollBack::RollWiteQuery(QSqlDatabase &_db, QSqlQuery &query)
{
    Q_UNUSED(_db);
    QString url = _setting.GetValue(VALUE_URL, "").toString();

    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;
        // 添加  dllVersion + serverUrl  辅助信息;
        if ( !json.contains(JSON_KEY_DLLVER) )
            json.insert(JSON_KEY_DLLVER, globalDllVersion);
        if ( !json.contains(JSON_KEY_SERVER_URL) )
             json.insert(JSON_KEY_SERVER_URL, url );

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

        QLOG_INFO() << "RollWiteQuery:: Get iv (partnerId+storeId+stationId): " << iv;

        if(!CretOperate::GetSign(json, iv)) {
            QLOG_ERROR() << "RollWiteQuery:: Get Sign Error";
            continue;
        }

        QLOG_INFO() << "RollWiteQuery:: " << json;
        QByteArray array;
        QString error;
        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() << "RollWiteQuery:: Result: " << 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();
            bool flag = query.exec("select * from orderlist");

            if(!flag)
                QLOG_WARN() << "RollBack::run " << 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::InsertRollOrder  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::InsertRollOrder  " << query.lastError() << query.lastError().text();
           } else {
                s_rollorder_lock.lock();
                s_rollorder.remove(it.key());
                s_rollorder_lock.unlock();
           }

        } else {
            QLOG_ERROR() << "RollBack:: InsertRollOrder Error: " << it.key() << it.value();
        }
    }

    s_rollorder_lock.lock();

    if(s_rollorder.size() > 300) {
        QLOG_WARN() << "RollBack:: Map Size Too Big, Need Clean,  Size=" << s_rollorder.size();
        s_rollorder.clear();
    }

    s_rollorder_lock.unlock();
}

void RollBack::SetRollOrder(QString orderid, QString request)
{
    QLOG_INFO() << "RollBack::SetRollOrder  New Roll Order: " << orderid << request;
    s_rollorder_lock.lock();
    s_rollorder.insert(orderid, request);
    s_rollorder_lock.unlock();
}
