#include "fmnetwork.h"
#include <QTimer>
#include <QSettings>
#include <QEventLoop>
#include <QSslSocket>
#include <QSslConfiguration>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QFutureWatcher>
#include <QJsonDocument>
#include "tools.h"
#include "fmglobal.h"
#include "QsLog.h"
#include "fmtool.h"
#include "fmp_settings.h"
#include <QtConcurrent>
#include <QLibrary>


FMNetWork::FMNetWork(QObject *parent) : QObject(parent)
{

}

bool FMNetWork::HttpPost(QString url, QByteArray &outdata, const QByteArray &indata, QString content, QString accept, QString  &error, int timeout)
{
    FMPSettings setting;
    QString host = setting.GetValue(VALUE_HOST, "").toString();

    QEventLoop loop;
    QTimer timer;

    QSslConfiguration config = QSslConfiguration::defaultConfiguration();
    config.setPeerVerifyMode(QSslSocket::VerifyNone);

    QNetworkAccessManager manger;
    QNetworkRequest request(url);

    request.setSslConfiguration(config);

    request.setRawHeader("Content-Type", content.toUtf8());
    request.setRawHeader("Accept", accept.toUtf8());
    request.setRawHeader("Host", host.toUtf8());
    request.setRawHeader("Authorization", "Basic dXBzLWNsaWVudDo2VGk4TjBXNzRyb1A=");
    if(setting.GetValue(CONFIG_ALL_PARTNER, SPCC).toInt() == SPCC) {
        QString action = setting.GetValue(CONFIG_OLTP_ACTION, "FromPOS").toString();
        request.setRawHeader("SOAPAction", action.toUtf8());
        QLOG_INFO() << "SPCC request action: " << action;
    }

    QLOG_INFO() << "HttpPost url: " << url << " content: " << content << " accept: " << accept << " timeout: " << timeout;

    QNetworkReply* reply = manger.post(request, indata);

    connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
    connect(&manger, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
    connect(reply, static_cast<void (QNetworkReply::*)(QNetworkReply::NetworkError)>(&QNetworkReply::error), &loop, &QEventLoop::quit);
    timer.start(timeout*1000);

    loop.exec();

    reply->deleteLater();

    if(reply->error() != QNetworkReply::NoError)
    {
        QLOG_ERROR() << reply->errorString();
        error = QString::fromLocal8Bit("网络异常");
        return false;
    }

    outdata = reply->readAll();

    if(outdata.isEmpty())
    {
        error = QString::fromLocal8Bit("返回数据为空");
        return false;
    }

    QLOG_INFO() << "HttpPost response: " << outdata.data();

    return true;
}

QByteArray FMNetWork::CreateOLTPXML(const QJsonObject &json)
{
    FMPSettings setting;
    QString reqXmlStr = QString::fromLocal8Bit("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
                                              "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"><SOAP-ENV:Body>"
                                                 "<ns0:OLTP xmlns:ns0=\"http://spcc.com.cn/online\">"
                                                     "<ns0:HEADER>"
                                                        "<ns0:VER>%1</ns0:VER>"
                                                     "<ns0:FROM>%2</ns0:FROM>"
                                                        "<ns0:TERMINO>%3</ns0:TERMINO>"
                                                        "<ns0:TO>%4</ns0:TO>"
                                                        "<ns0:BUSINESS>%5</ns0:BUSINESS>"
                                                        "<ns0:DATE>%6</ns0:DATE>"
                                                        "<ns0:TIME>%7</ns0:TIME>"
                                                        "<ns0:STATCODE>%8</ns0:STATCODE>"
                                                        "<ns0:STATDESC/>"
                                                    "</ns0:HEADER>"
                                                    "<ns0:AP>"
                                                        "%9"
                                                    "</ns0:AP>"
                                                "</ns0:OLTP>"
                                               "</SOAP-ENV:Body></SOAP-ENV:Envelope>");
    QString nsTo = "CS00400004";
    int type = FMTool::GetJsonValue(json, JSON_KEY_REQTYPE).toInt(sign);
    if(type==sign) {
        nsTo = "CS00400003";
    }
    QString date = QDate::currentDate().toString("yyMMdd");
    QString time = QTime::currentTime().toString("hhmmss");
    QString storeId = FMTool::GetJsonValue(json, JSON_KEY_STOREID).toString();
    QString posId = FMTool::GetJsonValue(json, JSON_KEY_STATIONID).toString();

    qsrand(QDateTime::currentMSecsSinceEpoch());
    QString termino = QString::fromUtf8("%1%2%3%4%5").arg(date).arg(storeId, 6, '0').arg(posId, 6, '0').arg(qrand()%90+10).arg(time);

    QByteArray jsonArray = QJsonDocument(json).toJson(QJsonDocument::Compact);

    reqXmlStr = reqXmlStr.arg(setting.GetValue(CONFIG_OLTP_VER, "01.01").toString())
            .arg(setting.GetValue(CONFIG_OLTP_FROM, "CS00000001").toString())
            .arg(termino)
            .arg(nsTo)
            .arg(setting.GetValue(CONFIG_OLTP_BUSINESS, "0000000").toString())
            .arg(QDate::currentDate().toString("yyyyMMdd"))
            .arg(time)
            .arg(setting.GetValue(CONFIG_OLTP_STATCODE, "0000").toString())
            .arg(QString::fromUtf8(jsonArray));

    QLOG_INFO() << "OLTP request xml data: " << reqXmlStr;

    return reqXmlStr.toUtf8();
}


bool FMNetWork::RequestToOLTP(const QJsonObject &json, QByteArray &outdata, QString &error, int timeout)
{
    QByteArray reqXmlData = FMNetWork::CreateOLTPXML(json);

#ifdef MOCK
    QLOG_DEBUG() << "=========================================== Read debug data. ========================================";
    int type = FMTool::GetJsonValue(json, JSON_KEY_REQTYPE).toInt(sign);
    QLOG_DEBUG() << "Test req type: " << type;
    QFile f(qApp->applicationDirPath()+QString("/test_spcc/%1.txt").arg(type));
    f.open(QIODevice::ReadOnly);
    strcpy(out, f.readAll().data());
    Sleep(1000*3);
    QLOG_DEBUG() << "=========================================== End read debug data. ====================================";

    int result = 0;
#else

    FMPSettings setting;
    QString url = setting.GetValue(CONFIG_OLTP_URL, "http://172.170.4.207:8080/OLTP/WSPortal").toString();
    QString uuid = QUuid::createUuid().toString().remove('{').remove('}');
    bool httpIsOk = FMNetWork::HttpPost(url, outdata, reqXmlData, "application/soap+xml; charset=utf-8", uuid, error, timeout);
#endif //! End def MOCK

    QString outXMlString = QString::fromUtf8(outdata);

    if(!httpIsOk) {
        error = "OLTP return error: \n" +error;
        QLOG_ERROR() << error;
        return false;
    } else {
        QString statcode;
        bool isOk = FMTool::SearchXMLNodeString(outXMlString, "ns0:STATCODE", statcode);
        if(!isOk) {
            error = "Can't find xml node: ns0:STATCODE";
            QLOG_ERROR() << error;
            return false;
        }
        if(statcode.compare("0000")!=0) {
            error = "OLTP return STATCODE is: " + statcode;
            QLOG_ERROR() << error;
            return false;
        }

        QString returnStr;
            isOk = FMTool::SearchXMLNodeString(outXMlString, "ns0:AP", returnStr);
            if(!isOk) {
                error = "Can't find xml node: ns0:AP";
                QLOG_ERROR() << error;
                return false;
            }
            outdata = returnStr.toUtf8();
            return true;
        }

    return false;
}
