#include "wbillcontrol.h"
#include <QtSql/QSqlError>
#include <QtSql/QSqlQuery>
#include <QVariant>
#include <QDebug>
#include <QSettings>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QJsonObject>
#include <QJsonDocument>
#include <QEventLoop>
#include <QTimer>
#include <QJsonArray>
#include <QDataStream>
#include <QCryptographicHash>
#include <QThread>
#include <QMapIterator>
#include <QTcpSocket>
#include "QsLog.h"
#include "Util/IniDataManger.h"
#include "DClasses/Database.h"
#include "BillsManger.h"

QThread g_thread;

WBillControl &WBillControl::GetInstance()
{
    static WBillControl wbc;
    return wbc;
}

WBillControl::WBillControl()
{
    this->moveToThread(&g_thread);
    g_thread.start();
    GetPosMenu();
}

WBillControl::~WBillControl()
{
    g_thread.quit();
    g_thread.wait();
}

void WBillControl::SetRemoteInfo(const QString &url)
{
    m_host = url;
}

void WBillControl::SetStoreInfo(const QString &partner_id, const QString &storeId, const QString &operaId, const QString &posId, const QString &dbusiness)
{
    QLOG_TRACE() << "WBillControl::SetStoreInfo" <<partner_id<< storeId << operaId << posId << dbusiness;
    QLOG_TRACE() << "WBillControl::SetStoreInfo" << QThread::currentThreadId();
    m_partner_id = partner_id;
    m_storeId = storeId;
    m_operatorId = operaId;
    m_posId = posId;
    m_dbusiness = dbusiness;
}

void WBillControl::DoOrderEntry(const OrderObject *orderObject)
{
    QTcpSocket *socket = new QTcpSocket(this);
    // 连接
    QByteArray byteSlip=GetOrderEntryData(orderObject, false);
    QLOG_INFO() << "write order:"<<byteSlip.data();
    QLOG_INFO() << "ip:"<<IniDataManger::Instance().GetPOSServerIP();
    socket->connectToHost(IniDataManger::Instance().GetPOSServerIP(), 23772);
    if (socket->waitForConnected())
    {
        if(SendToMonitor(byteSlip,socket)){
            // 接收返回
            if (socket->waitForReadyRead())
            {
                QJsonObject recvJson =  QJsonDocument::fromJson(socket->readAll()).object();
                QLOG_INFO() <<"write order back:"<< recvJson;
                bool res=1;
                if(recvJson["statusCode"].toInt()!=100)
                {
                    res=0;
                    QLOG_INFO() << "write order failed:" << recvJson["msg"].toString();
                }
                QString sql = QString("update %1 set products_fee=%2,shop_fee=%3,isPosOK=%4 where fm_id='%5';")
                        .arg(Database::getInstance().GetInfoTableName())
                        .arg(orderObject->product_fee).arg(orderObject->shop_fee).arg(res).arg(orderObject->fm_id);
                if(Database::getInstance().execSql(sql)){
                    emit sUpdatePosRes(orderObject);
                }

            }
        }
    }
    socket->close();
}

void WBillControl::RefundOrder(const QString &fmId)
{
    QTcpSocket *socket = new QTcpSocket(this);
    // 连接
    QByteArray byteSlip=GetRefundOrderData(fmId);
    QLOG_INFO() << "refund order:"<<byteSlip.data();

    //socket->connectToHost("127.0.0.1", 23772);
    socket->connectToHost(IniDataManger::Instance().GetPOSServerIP(), 23772);
    if (socket->waitForConnected())
    {
        if(SendToMonitor(byteSlip,socket)){
            // 接收返回
            if (socket->waitForReadyRead())
            {
                QJsonObject recvJson =  QJsonDocument::fromJson(socket->readAll()).object();
                QLOG_INFO() << "refund order back:"<<recvJson;
                bool res=1;
                if(recvJson["statusCode"].toInt()!=100)
                {
                    res=0;
                    QLOG_INFO() << "write order failed:" << recvJson["msg"].toString();
                }
                QString sql = QString("update %1 set isPosRefundOK=%2 where fm_id='%3';")
                        .arg(Database::getInstance().GetInfoTableName()).arg(res).arg(fmId);
                Database::getInstance().execSql(sql);
            }
        }
    }
    socket->close();
}

QByteArray WBillControl::GetOrderEntryData(const OrderObject *orderObject, bool bVerify)
{
    QJsonObject rObj, cObj;
    if(bVerify)
    {
        rObj.insert("fm_cmd", "put_order_check");
    }else
    {
        rObj.insert("fm_cmd", "put_order");
    }

    rObj.insert("fm_ver", "1.0");

    cObj.insert("pay_id", "002");
    cObj.insert("pay_str", QString("非码外卖"));
    cObj.insert("pay_ebcode", orderObject->channel);
    cObj.insert("pay_ebcode_str", orderObject->channelName);
    cObj.insert("shop_fee", orderObject->shop_fee);
    cObj.insert("service_fee", orderObject->service_fee);
    cObj.insert("products_fee", orderObject->product_fee);
    cObj.insert("discount_fee", orderObject->discount_fee);
    cObj.insert("dis_shop_fee", orderObject->dis_shop_fee);
    cObj.insert("send_fee", orderObject->send_fee);
    cObj.insert("package_fee", orderObject->package_fee);
    cObj.insert("invoice_amount", 0);
    cObj.insert("paid_trans_id", orderObject->order_id);
    cObj.insert("fm_id", orderObject->fm_id);
    cObj.insert("customer_address", orderObject->address);
    cObj.insert("customer_name", orderObject->customer);
    cObj.insert("customer_phone", orderObject->phone);
    cObj.insert("delivery_time", orderObject->delivery_time);
    cObj.insert("order_index", orderObject->order_index);
    cObj.insert("remark", orderObject->remark);
    cObj.insert("dis_platform_fee", 0);

    rObj.insert("pay_id", cObj);

    QJsonArray tAry;
    for(int i=0; i < orderObject->pvm.keys().count(); i++)
    {

        QJsonObject tObj;
        tObj.insert("consume_num", orderObject->proList.at(i)->productAmount);
        tObj.insert("pid", orderObject->proList.at(i)->pid);
        tObj.insert("original_price", orderObject->proList.at(i)->price);
        tAry.insert(i, tObj);
    }
    rObj.insert("products", tAry);

    qDebug() << rObj;
    QJsonDocument doc(rObj);
    QString strArray = QString(doc.toJson( QJsonDocument::Compact));
    return strArray.toUtf8();
}

QByteArray WBillControl::GetRefundOrderData(const QString &fmId)
{
    QJsonObject rObj;
    rObj.insert("fm_cmd", "refund_order");
    rObj.insert("fm_ver", "1.0");
    rObj.insert("fm_id", fmId);

     qDebug() << "退款数据" << rObj;
    QJsonDocument doc(rObj);
    QString strArray = QString(doc.toJson( QJsonDocument::Compact));
    return strArray.toUtf8();
}

bool WBillControl::SendToMonitor(const QByteArray &data,QTcpSocket *pSocket)
{
    bool result=true;
    //QTcpSocket client;

    int jsonLength=data.length();
    char* m_pFmPackage = new char[jsonLength + sizeof(FMSOCKEHEADER)];
    FMSOCKEHEADER header = { 0, 0, 0 };
    header.flag = 0x4d46;
    header.len = jsonLength;
    header.ver = 0x1;

    memcpy(m_pFmPackage, &header, sizeof(FMSOCKEHEADER));
    memcpy(m_pFmPackage+sizeof(FMSOCKEHEADER), data, jsonLength);


    int toSendLength = jsonLength + sizeof(FMSOCKEHEADER);
    int curSendLength = 0;

    while(curSendLength < toSendLength)
    {
        int rlt= pSocket->write(m_pFmPackage+curSendLength,toSendLength - curSendLength);
        pSocket->waitForBytesWritten();
        if(rlt==-1){
            QLOG_ERROR() << QString::fromLocal8Bit("发送数据失败：") << data;
            result=false;
            break;
        }
        curSendLength += rlt;
    }

    delete[] m_pFmPackage;
    return result;
}

void WBillControl::GetPosMenu()
{
    QTcpSocket *socket = new QTcpSocket(this);
    // 连接
    QJsonObject rObj;
    rObj.insert("fm_cmd", "get_menu");
    rObj.insert("fm_ver", "1.0");
    QJsonDocument doc(rObj);

    QByteArray byteSlip=QString(doc.toJson( QJsonDocument::Compact)).toUtf8();
    QLOG_INFO() << "------------------------------get_menu:"<<byteSlip.data();

    socket->connectToHost(IniDataManger::Instance().GetPOSServerIP(), 23772);
    if (socket->waitForConnected())
    {
        if(SendToMonitor(byteSlip,socket)){
            // 接收返回
            bool flag=true;
            QByteArray arr;
            while(flag){
                if (socket->waitForReadyRead())
                {
                    arr.push_back(socket->readAll());
                    QJsonObject recvJson =  QJsonDocument::fromJson(arr).object();
                    if(!recvJson.isEmpty())
                        flag=false;
                }
            }
           // QLOG_INFO() << "------------------------------menu json:"<<arr.data();
            setMenu(arr);
        }
    }
    socket->close();
}

void WBillControl::setMenu(const QByteArray &JsonMenu)
{
    //QMap<QString,QVector<SetMenuItem>> mapSetMenu;
    vecMenu.clear();
    mapSetMenu.clear();
    QJsonObject recvJson =  QJsonDocument::fromJson(JsonMenu).object();
    QJsonArray orders = recvJson["MenuList"].toArray();
    PrinterMenu menu;
    foreach (QJsonValue order, orders) {
       QJsonObject orderObj = order.toObject();
       menu.strMenuId = orderObj["strMenuId"].toString();
       menu.strMenuName = orderObj["strMenuName"].toString();
       menu.iPrinterId = orderObj["iPrinterId"].toInt();
       menu.strDevice = orderObj["strDevice"].toString();

       menu.iBaud = orderObj["iBaud"].toInt();
       menu.strTitle = orderObj["strTitle"].toString();
       menu.iOrderPrinterId = orderObj["iOrderPrinterId"].toInt();
       menu.strOrderDevice = orderObj["strOrderDevice"].toString();
       menu.iOrderBaud = orderObj["iOrderBaud"].toInt();
       menu.strOrderTitle = orderObj["strOrderTitle"].toString();
       vecMenu.push_back(menu);
    }

    QJsonArray arrySetMenuList = recvJson["SetMenuMap"].toArray();
    foreach (QJsonValue order, arrySetMenuList){
        QJsonObject orderObj = order.toObject();
        QString setMenuId = orderObj["strSetMenuId"].toString();

        QVector<SetMenuItem> vecItem;
        QJsonArray arrayItems = orderObj["arrayItems"].toArray();
        foreach (QJsonValue orderItem, arrayItems){
            SetMenuItem item;
            QJsonObject objItem = orderItem.toObject();
            item.strMenuId = objItem["strMenuId"].toString();
            item.num = objItem["iNum"].toInt();
            vecItem.push_back(item);
        }
        mapSetMenu.insert(setMenuId,vecItem);
    }
}

void WBillControl::PrintLable(const OrderObject *obj)
{
    QVector<QString> vecPid;
    for(int i=0; i < obj->pvm.keys().count(); i++)
    {
        QString pid=obj->proList.at(i)->pid;
        vecPid.push_back(pid);
        for(PrinterMenu menu:vecMenu){
            if(menu.strMenuId==pid){
                //print
                //...
                break;
            }
        }
    }

}
