#ifndef CRETOPT
#define CRETOPT

#include "dataprocess.h"

#include <string>
#include <QFile>
#include <QString>
#include <QJsonObject>
#include <QJsonDocument>
#include "QsLog.h"
#include "tools.h"
class CretOperate
{
public:
    static bool GetDES3MAC(QJsonObject &json, QString iv, QString &mac = QString())
    {
        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};

//        if(DataProcess::DES3Encode((const unsigned char *)DES3_KEY, tmpmac.data(), strlen(tmpmac.data()), (unsigned char *)outmsg, 4096) == 0)
//        {
//            QLOG_ERROR() << "DES3 MAC failed";
//            return false;
//        }

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

        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)
    {
        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, QString iv)
    {
        QByteArray array = des3text;

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

//        if(DataProcess::DES3Decode((const unsigned char *)DES3_KEY, buf, strlen(buf), (unsigned char *)rps, MAX_BUF_LEN) == 0)
//        {
//            QLOG_ERROR() << "DES3Decode des3text Failed";
//            return false;
//        }

        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());

        if(DataProcess::AESDecode((const unsigned char *)AES_KEY, (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::DES3Encode((const unsigned char *)DES3_KEY_PRT, data.data(), strlen(data.data()), (unsigned char *)prtrps, MAX_BUF_LEN) == 0)
//        {
//            QLOG_ERROR() << "3des private client.p12 file:" << json;
//            return false;
//        }

        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 client.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 client.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());

//        if(DataProcess::DES3Decode((const unsigned char *)DES3_KEY_PRT, buf, strlen(buf), (unsigned char *)rps, MAX_BUF_LEN) == 0)
//        {
//            QLOG_ERROR() << "DES3Decode Client.p12 Failed";
//            return false;
//        }

        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 client.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

