#ifndef CRETOPT
#define CRETOPT

#include "dataprocess.h"
#include <string>
#include <QFile>
#include <QString>
#include <QJsonObject>
#include <QJsonDocument>
#include "QsLog.h"
#include "tools.h"
#include "fmp_settings.h"

class CretOperate
{
public:

    static bool GetDES3MAC(QJsonObject &json, const int region , QString iv )
    {
        std::string tmpmac;
        if(ToolS::GetMacByGetAdaptersAddresses(tmpmac) == 0) {
            QLOG_ERROR() << "get MAC failed";
            return false;
        }
        QLOG_INFO() << tmpmac.data();
        char tmpiv[16] = {0};
        memcpy(tmpiv, iv.toUtf8().data(), iv.toUtf8().size() > 16 ? 16 : iv.toUtf8().size());
        char outmsg[4096] = {0};

        QString aes_key = "";
        if ( EC_REGION == region ) {
            aes_key = EC_ADES3_KEY;
        } else {
            aes_key = CCO_ADES3_KEY;
        }

        if(DataProcess::AESEncode((const unsigned char *)aes_key.toUtf8().data(), (unsigned char *)tmpiv,
                                  (const unsigned char *)tmpmac.data(), strlen(tmpmac.data()), (unsigned char *)outmsg, 4096) == 0)
        {
            QLOG_ERROR() << "AES MAC failed";
            return false;
        }

        QString mac = QString(outmsg);
        json.insert(JSON_KEY_MAC, mac);
        QLOG_INFO() << mac;
        return true;
    }

    static bool GetMAC(QJsonObject &json, QString &mac = QString())
    {
        std::string tmpmac;
        if(ToolS::GetMacByGetAdaptersAddresses(tmpmac) == 0) {
            QLOG_ERROR() << "get MAC failed";
            return false;
        }
        mac = QString::fromStdString(tmpmac);
        json.insert(JSON_KEY_MAC, mac);
        QLOG_INFO() << mac;
        return true;
    }

    static bool RSASign(QJsonObject &json, QString &sign)
    {
        Q_UNUSED(json);
        Q_UNUSED(sign);
        return true;
    }

    static bool GetSign(QJsonObject &json, QString iv, QString &sign = QString())
    {
        QString serpbk, clipbk;
        if(!GetCret(iv, serpbk, clipbk))
            return false;

        QStringList list;
        QString values;
        DataProcess::GetJsonKeyArray(list, json);
        DataProcess::SortString(list);
        DataProcess::GetValueFromJson(list, json, values);
        QByteArray array = values.toUtf8();
        char tmp[MAX_SIGN_LEN] = { 0 };

        if(DataProcess::RSASign(array.data(), tmp, MAX_SIGN_LEN, clipbk.toUtf8().data()) == 0) {
            QLOG_ERROR() << "get RSASign failed";
            return false;
        }

        QLOG_INFO() << "get RSA sign:" << tmp;
        sign = QString(tmp);
        json.insert(JSON_KEY_SIGN, sign);
        return true;
    }

    static bool SetRSACret(QByteArray &des3text,  const int region , QString iv)
    {
        QByteArray array = des3text;
        char rps[MAX_BUF_LEN] = {0};
        char *buf = (char *)calloc(array.size() + 100, sizeof(char));
        strcpy(buf, array.data());
        char tmpiv[16] = {0};
        char tmpiv1[16] = {0};

        memcpy(tmpiv, iv.toUtf8().data(), iv.toUtf8().size() > 16 ? 16 : iv.toUtf8().size());
        memcpy(tmpiv1, iv.toUtf8().data(), iv.toUtf8().size() > 16 ? 16 : iv.toUtf8().size());

        QString aes_key = "";
        if ( EC_REGION == region ) {
            aes_key = EC_ADES3_KEY;
        } else {
            aes_key = CCO_ADES3_KEY;
        }

        if(DataProcess::AESDecode((const unsigned char *)aes_key.toUtf8().data(), (unsigned char *)tmpiv,
                                  (const unsigned char *)buf, strlen(buf), (unsigned char *)rps, MAX_BUF_LEN) == 0)
        {
            QLOG_ERROR() << "AESDecode AEStext Failed";
            return false;
        }

        QJsonDocument jsonDocument = QJsonDocument::fromJson(QByteArray(rps));

        if( jsonDocument.isNull() ) {
            QLOG_ERROR() << "AESDecode not json:" << rps;
            return false;
        }

        QJsonObject json = jsonDocument.object();

        if(!json.contains(JSON_KEY_STATUS) || json[JSON_KEY_STATUS].toInt() != 100) {
            QLOG_ERROR() << "error des3text file:" << json;
            return false;
        }

        //验证证书合法性在此添加
        QByteArray data = QJsonDocument(json).toJson(QJsonDocument::Compact);
        char prtrps[MAX_BUF_LEN] = {0};

        if(DataProcess::AESEncode((const unsigned char *)AES_KEY_PRT, (unsigned char *)tmpiv1,
                                  (const unsigned char *)data.data(), strlen(data.data()), (unsigned char *)prtrps, MAX_BUF_LEN) == 0)
        {
            QLOG_ERROR() << "AES private simphonyclient.p12 filed:" << json;
            return false;
        }

        char path[MAX_PATH] = { 0 };
        ToolS::GetProcPath(path);
        QString p12path(path);
        p12path.append(CRET_FILE_NAME);
        QFile file(p12path);

        if(!file.open(QFile::WriteOnly)) {
            QLOG_ERROR() << QString("open %1 failed").arg(p12path);
            return false;
        }

        file.write(prtrps);
        file.flush();
        file.close();
        QLOG_INFO() << "write simphonyclient.p12 success";

        return true;
    }

private:

    static bool GetCret(QString iv, QString &serpublickey, QString &cleprivatekey)
    {
        if(iv.isEmpty()) {
            QLOG_ERROR() << "AES cbc iv is empty";
            return false;
        }

        char path[MAX_PATH] = { 0 };
        ToolS::GetProcPath(path);
        QString p12path(path);
        p12path.append(CRET_FILE_NAME);
        QFile file(p12path);

        if(!file.open(QFile::ReadOnly)) {
            QLOG_ERROR() << QString("open %1 failed").arg(p12path);
            return false;
        }

        QByteArray array = file.readAll();
        file.close();

        char rps[MAX_BUF_LEN] = {0};
        char *buf = (char *)calloc(array.size() + 100, sizeof(char));
        strcpy(buf, array.data());
        char tmpiv[16] = {0};

        memcpy(tmpiv, iv.toUtf8().data(), iv.toUtf8().size() > 16 ? 16 : iv.toUtf8().size());

        if(DataProcess::AESDecode((const unsigned char *)AES_KEY_PRT, (unsigned char *)tmpiv,
                                  (const unsigned char *)buf, strlen(buf), (unsigned char *)rps, MAX_BUF_LEN) == 0)
        {
            QLOG_ERROR() << "AESDecode AEStext Failed";
            return false;
        }

        QJsonDocument jsonDocument = QJsonDocument::fromJson(QByteArray(rps));

        if( jsonDocument.isNull() ) {
            QLOG_ERROR() << "AESDecode not json:" << rps;
            return false;
        }

        QJsonObject json = jsonDocument.object();

        if(!json.contains(JSON_KEY_STATUS) || json[JSON_KEY_STATUS].toInt() != 100) {
            QLOG_ERROR() << "error simphonyclient.p12 file:" << json;
            return false;
        }

        serpublickey = json[JSON_KEY_SERPBLICKEY].toString();
        cleprivatekey = json[JSON_KEY_CLIENTPRIKEY].toString();

#ifdef FM_DEBUG
        QLOG_INFO() << "server public key : " << serpublickey;
        QLOG_INFO() << "client private key : " << cleprivatekey;
#endif

        return true;
    }
};

#endif // CRETOPT
