#ifndef RSPFACTORY
#define RSPFACTORY

#include "requestmodel.h"
#include "global.h"
#include "fmtool.h"
#include "QsLog.h"

#include <QFile>
#include <QDir>
#include <QJsonObject>
#include <QApplication>

class RspFactory
{
public:
    static bool GetResPonseJson(ReqType type, AlipayResponse &response, const QJsonObject &json)
    {

        if(json.isEmpty())
            return false;

        memset(&response, ' ', sizeof(response));

        if(type == pay)
            return GetPayResponse(response, json);
        if(type == refund)
            return GetRefundResponse(response, json);
        if(type == endday)
            return GetDayEndResponse(response, json);
        if(type == againprint)
            return GetAgainPrinteResponse(response, json);
        if(type == finds)
            return GetFindResponse(response, json);
        return false;
    }


    static bool GetResPonseJson(ReqType type, QJsonObject &response, const QJsonObject &json)
    {

        if(json.isEmpty())
            return false;

        if(type == sign)
            return GetSignResponse(response, json);
        if(type == pay)
            return GetPayResponse(response, json);
        if(type == refund)
            return GetRefundResponse(response, json);
        if(type == endday)
            return GetEndDayResponse(response, json);
        if(type == shift)
            return GetShiftResponse(response, json);
        if(type == finds)
            return GetFindResponse(response, json);
        return false;
    }


    static bool GetResPonseWithError(AlipayResponse &response, QString errorcode, QString message)
    {
        if(errorcode.isEmpty() || message.isEmpty())
            return false;

        memset(&response, ' ', sizeof(response));

        FMTool::SetString(response.ResponseCode, 3, errorcode);
        FMTool::SetString(response.ResponseMsg, 3, message);

        return true;
    }

#ifndef FM_TEST
private:
#endif

    static bool GetSignResponse(QJsonObject &response, const QJsonObject &json)
    {
        response = json;
        return true;
    }

    static bool GetPayResponse(AlipayResponse &response, const QJsonObject &json)
    {
        FMTool::SetString(response.ResponseCode, 3, QString::number(json[JSON_KEY_STATUSCODE].toInt()));
        FMTool::SetString(response.ResponseMsg, 40, json[JSON_KEY_MESSAGE].toString());
        FMTool::SetString(response.CardTraceNo, 40, json[JSON_KEY_FMID].toString());
        //MTool::SetString(response.CardTraceNo, 40, "99571708191000040011");
        FMTool::SetString(response.NeedPrint, 2, QString("01"));
        int transAmount = json[JSON_KEY_TRANSAMOUNT].toInt();
        int merchantDiscount = json[JSON_KEY_MERDISCOUNT].toInt();
        int platformDiscount = json[JSON_KEY_PLTDISCOUNT].toInt();
        int userAmount = transAmount - merchantDiscount - platformDiscount;

        QString number;

        {
            //用户实付
            struct EFTItem *item = (struct EFTItem *)response.EFT_Detail_information[0];

            FMTool::SetString((void *)&(item->billType), 1, "1");
            FMTool::SetString((void *)&(item->billId), 8, QString("36464"));
            FMTool::SetString((void *)&(item->amount), 12, QString::number(userAmount));
            FMTool::SetString((void *)&(item->transactionNum), 64, json[JSON_KEY_FMID].toString());
            //FMTool::SetString((void *)&(item->transactionNum), 64, "99571708191000040011");
            number = "01";
        }


        if(merchantDiscount != 0)
        {
            //商户补贴
            struct EFTItem *item = (struct EFTItem *)response.EFT_Detail_information[1];

            FMTool::SetString((void *)&(item->billType), 1, "1");
            FMTool::SetString((void *)&(item->billId), 8, QString("36466"));
            FMTool::SetString((void *)&(item->amount), 12, QString::number(merchantDiscount));
            //FMTool::SetString((void *)&(item->amount), 12, QString("100"));
            FMTool::SetString((void *)&(item->transactionNum), 64, json[JSON_KEY_FMID].toString());
            number = "02";
        }

        if(platformDiscount != 0)
        {
            //支付宝补贴
            struct EFTItem *item = (struct EFTItem *)response.EFT_Detail_information[2];

            FMTool::SetString((void *)&(item->billType), 1, "1");
            FMTool::SetString((void *)&(item->billId), 8,  QString("10001"));
            FMTool::SetString((void *)&(item->amount), 12, QString::number(platformDiscount));
            //FMTool::SetString((void *)&(item->amount), 12,  QString("100"));
            FMTool::SetString((void *)&(item->transactionNum), 64, json[JSON_KEY_FMID].toString());
            number = "03";
        }

        FMTool::SetString(response.EFT_quantity, 2, number);

        if(json[JSON_KEY_STATUSCODE].toInt() == 100)
            return SetPinter(response, json);
        return true;
    }

    static bool GetPayResponse(QJsonObject &response, const QJsonObject &json)
    {
        response[JSON_KEY_STATUSCODE] = FMTool::GetJsonValue(json, JSON_KEY_STATUSCODE).toInt();
        response[JSON_KEY_MESSAGE] = FMTool::GetJsonValue(json, JSON_KEY_MESSAGE).toString();
        response[JSON_KEY_EXT] = FMTool::GetJsonValue(json, JSON_KEY_EXT).toObject();
        response[JSON_KEY_FMID] = FMTool::GetJsonValue(json, JSON_KEY_FMID).toString();
        response[JSON_KEY_PAYACCOUNT] = FMTool::GetJsonValue(json, JSON_KEY_PAYACCOUNT).toString();
        response[JSON_KEY_PAYTRANSID] = FMTool::GetJsonValue(json, JSON_KEY_PAYTRANSID).toString();
        response[JSON_KEY_TYPE] = FMTool::GetJsonValue(json, JSON_KEY_TYPE).toInt();
        response[JSON_KEY_PAYMENTMETHOD] = FMTool::GetJsonValue(json, JSON_KEY_PAYMENTMETHOD).toString();
        response[JSON_KEY_PAYMENTMETHODCODE] = FMTool::GetJsonValue(json, JSON_KEY_PAYMENTMETHODCODE).toString();
        response[JSON_KEY_TRANSAMOUNT] = FMTool::GetJsonValue(json, JSON_KEY_TRANSAMOUNT).toInt();
        response[JSON_KEY_MERDISCOUNT] = FMTool::GetJsonValue(json, JSON_KEY_MERDISCOUNT).toInt();
        response[JSON_KEY_PLTDISCOUNT] = FMTool::GetJsonValue(json, JSON_KEY_PLTDISCOUNT).toInt();
        return true;
    }

    static bool GetRefundResponse(AlipayResponse &response, const QJsonObject &json)
    {
        FMTool::SetString(response.ResponseCode, 3, QString::number(json[JSON_KEY_STATUSCODE].toInt()));
        FMTool::SetString(response.ResponseMsg, 40, json[JSON_KEY_MESSAGE].toString());
        FMTool::SetString(response.CardTraceNo, 40, json[JSON_KEY_FMID].toString());
        FMTool::SetString(response.NeedPrint, 2, QString("01"));

        int transAmount = json[JSON_KET_CLIENTREF].toString().toInt();
        int merchantDiscount = json[JSON_KEY_MERDISCOUNT].toInt();
        int platformDiscount = json[JSON_KEY_PLTDISCOUNT].toInt();
        int userAmount = transAmount - merchantDiscount - platformDiscount;

        QString number;

        if(json[JSON_KEY_STATUSCODE].toInt() == 100)
        {
            struct EFTItem *item = (struct EFTItem *)response.EFT_Detail_information[0];

            FMTool::SetString((void *)&(item->billType), 1, "1");
            FMTool::SetString((void *)&(item->billId), 8, QString("36464"));
            FMTool::SetString((void *)&(item->amount), 12, QString::number(userAmount));
            FMTool::SetString((void *)&(item->transactionNum), 64, json[JSON_KEY_FMID].toString());
            number = "01";
        }

        FMTool::SetString(response.EFT_quantity, 2, number);

        if(json[JSON_KEY_STATUSCODE].toInt() == 100)
            return SetPinter(response, json);
        return true;

    }

    static bool GetRefundResponse(QJsonObject &response, const QJsonObject &json)
    {
        response[JSON_KEY_STATUSCODE] = FMTool::GetJsonValue(json, JSON_KEY_STATUSCODE).toInt();
        response[JSON_KEY_MESSAGE] = FMTool::GetJsonValue(json, JSON_KEY_MESSAGE).toString();
        response[JSON_KEY_EXT] = FMTool::GetJsonValue(json, JSON_KEY_EXT).toObject();
        response[JSON_KEY_FMID] = FMTool::GetJsonValue(json, JSON_KEY_FMID).toString();
        return true;
    }

    static bool GetDayEndResponse(AlipayResponse &response, const QJsonObject &json)
    {
        FMTool::SetString(response.ResponseCode, 3, QString::number(json[JSON_KEY_STATUSCODE].toInt()));
        FMTool::SetString(response.ResponseMsg, 40, json[JSON_KEY_MESSAGE].toString());
        FMTool::SetString(response.NeedPrint, 2, QString("01"));

        if(json[JSON_KEY_STATUSCODE].toInt() == 100)
            return SetPinter(response, json);
        return true;
    }


    static bool GetEndDayResponse(QJsonObject &response, const QJsonObject &json)
    {
        response[JSON_KEY_STATUSCODE] = json[JSON_KEY_STATUSCODE];
        response[JSON_KEY_MESSAGE] = json[JSON_KEY_MESSAGE];

        if(json[JSON_KEY_STATUSCODE].toInt() == 100)
            return SetPinter(response, json, PRINT_ENDDAY_FILE_NAME);
        return true;
    }
    static bool GetShiftResponse(QJsonObject &response, const QJsonObject &json)
    {
        response[JSON_KEY_STATUSCODE] = json[JSON_KEY_STATUSCODE];
        response[JSON_KEY_MESSAGE] = json[JSON_KEY_MESSAGE];

        if(json[JSON_KEY_STATUSCODE].toInt() == 100)
            return SetPinter(response, json, PRINT_SHIFT_FILE_NAME);
        return true;
    }

    static bool GetAgainPrinteResponse(AlipayResponse &response, const QJsonObject &json)
    {
        FMTool::SetString(response.ResponseCode, 3, QString::number(json[JSON_KEY_STATUSCODE].toInt()));
        FMTool::SetString(response.ResponseMsg, 40, json[JSON_KEY_MESSAGE].toString());
        FMTool::SetString(response.CardTraceNo, 40, json[JSON_KEY_FMID].toString());
        FMTool::SetString(response.NeedPrint, 2, QString("01"));

        if(json[JSON_KEY_STATUSCODE].toInt() == 100)
            return SetAgainPinter(response, json);
        return true;
    }

    static bool GetFindResponse(AlipayResponse &response, const QJsonObject &json)
    {
        return false;
    }

    static bool GetFindResponse(QJsonObject &response, const QJsonObject &json)
    {
        response[JSON_KEY_STATUSCODE] = json[JSON_KEY_STATUSCODE];
        response[JSON_KEY_MESSAGE] = json[JSON_KEY_MESSAGE];
        return true;
    }

    static bool SetAgainPinter(AlipayResponse &response, const QJsonObject &json)
    {
        if(!json.contains(JSON_KEY_EXT) || !json[JSON_KEY_EXT].isObject())
            return false;

        FMTool::SetString(response.NeedPrint, 2, QString("00"));

        QJsonObject obj = json[JSON_KEY_EXT].toObject();
        QString str;
        str.append(obj[JSON_KEY_PRINT].toString());
        str.replace("#", "\r\n");
        str.append("==============================\r\n").append(QChar(27)).append(QChar('@')).append(QChar(29)).append("hP").append(QChar(29)).append(QChar('w')).append(QChar(2)).append(QChar(29)).append(QChar('H')).append(QChar(2));
        str.append(QChar(27)).append(QChar('a')).append(QChar(1)).append(QChar(29)).append("kF").append(QChar(20)).append(json[JSON_KEY_FMID].toString()).append("\r\n").append(QChar(27)).append('@').append('\r').append('\n');

        qDebug() << str;

        qDebug() << json;

        QFile file(qApp->applicationDirPath() + "/" + PRINT_FILE_NAME);
        QString path = qApp->applicationDirPath() + "/" + PRINT_FILE_NAME;
        FMTool::SetString(response.EFTprintFileName, 200, path.replace("/", "\\"));

        file.open(QFile::WriteOnly);

        if(!file.isOpen())
            return false;

        char array[MAX_PRINT_LEN] = { 0 };

        FMTool::SetStringWith(array, str.toUtf8().length(), str);

        file.write(array);

        file.flush();

        file.close();

        return true;
    }

    static bool SetPinter(AlipayResponse &response, const QJsonObject &json)
    {
        if(!json.contains(JSON_KEY_EXT) || !json[JSON_KEY_EXT].isObject())
            return false;

        FMTool::SetString(response.NeedPrint, 2, QString("00"));

        QJsonObject obj = json[JSON_KEY_EXT].toObject();
        QString str = obj[JSON_KEY_PRINT].toString();
        str.replace("#", "\r\n");
        str.append("\r\n");

        QFile file(qApp->applicationDirPath() + "/" + PRINT_FILE_NAME);
        QString path = qApp->applicationDirPath() + "/" + PRINT_FILE_NAME;
        FMTool::SetString(response.EFTprintFileName, 200, path.replace("/", "\\"));

        file.open(QFile::WriteOnly);

        if(!file.isOpen())
            return false;

        char array[MAX_PRINT_LEN] = { 0 };

        FMTool::SetStringWith(array, str.toUtf8().length(), str);

        file.write(array);

        file.flush();

        file.close();

        return true;
    }

    static bool SetPinter(QJsonObject &response, const QJsonObject &json, QString fileName=PRINT_ENDDAY_FILE_NAME)
    {
        if(!json.contains(JSON_KEY_EXT) || !json[JSON_KEY_EXT].isObject())
            return false;

        QJsonObject obj = json[JSON_KEY_EXT].toObject();
        QString str = obj[JSON_KEY_PRINT].toString();

        QDir dir(PRINT_FILE_PATH);
        if(!dir.exists()) {
            bool isOk = dir.mkpath(PRINT_FILE_PATH);
            QLOG_INFO() << "Make path: " << PRINT_FILE_PATH << (isOk ? " Success." : " Fail.");
        }

        QString filePath = PRINT_FILE_PATH + fileName;
        response[JSON_KEY_PRINTPATH] = filePath;
        QFile file(filePath);

        file.open(QFile::WriteOnly);

        if(!file.isOpen())
            return false;

        char buf[MAX_PRINT_LEN] = { 0 };

        FMTool::SetString(buf, str.toUtf8().length(), str);

        file.write(buf);

        file.flush();

        file.close();

        return true;
    }
};

#endif // RSPFACTORY

