/**
 * 收费
 */

import { INVOICESTATUS, MEMBERSTATE, ORDEREXAMINE, ORDERSTATE, PAYMENTSTATUS, PAYMENTTYPE, RECEIPTCONFIRMATION, STATE, WEICHARTPAYSTATE } from "../../config/enum";
import { TABLEENUM } from "../../data/models/model";
import { findCount, findOnce, findOnceToSort } from "../../data/select";
import * as path from "path";
const WxPay = require('wechatpay-node-v3');
import * as fs from 'fs';
import { BizError } from "../../util/bizError";
import { ERRORENUM } from "../../config/errorEnum";
import { generateWXOrderId, successResult } from "../../tools/system";
import { updateOneData } from "../../data/update";
import moment = require("moment");
import { systemConfig } from "../../config/serverConfig";
import { addOneData } from "../../data/add";

const AppId = 'wx96c0cf11b3babcf6';
const MchId = '1614605859';
const V3Key = 'c0338804d0c6a60cced9cad83a9a0402';
const pay = new WxPay({
    appid: AppId,
    mchid: MchId,
    publicKey: fs.readFileSync( path.join(__dirname.substring(0,__dirname.indexOf("out")), "keys", 'apiclient_cert.pem'  ) ), // 公钥
    privateKey: fs.readFileSync(  path.join(__dirname.substring(0,__dirname.indexOf("out")), "keys", 'apiclient_key.pem'  ) ), // 秘钥
});

/**
 * native下单接口【前端调用】
 * @param param0 {id订单列表的id}
 * @returns 
 */
export async function placeAnOrder({id}) {
    let orderInfo = await findOnce(TABLEENUM.订单表, {id}, ["id", "loginId", "userId", "memberCategory", "money", "orderCycleStart", "orderCycleEnd","weChartState", "state", "weChartCreatePayMs", "weChartPayUrl", "weChartPR", "confirmReceipt"]);
    if (!orderInfo || !orderInfo.id) throw new BizError(ERRORENUM.订单不存在);
    if (orderInfo.state == ORDERSTATE.已支付 && orderInfo.confirmReceipt != RECEIPTCONFIRMATION.退回) throw new BizError(ERRORENUM.该订单已支付);
    if (orderInfo.weChartCreatePayMs && orderInfo.weChartState == WEICHARTPAYSTATE.未支付) {
        if (new Date(orderInfo.weChartCreatePayMs).valueOf() < (new Date().valueOf() + (15 * 60 * 1000)) ) {
            return {code_url:orderInfo.weChartPayUrl, weChartPR:orderInfo.weChartPR};
        }
    }
    
    /**生成 out_trade_no */
    let out_trade_no = generateWXOrderId(orderInfo.memberCategory, orderInfo.userId);
    let desc = `${orderInfo.loginId}_${moment(orderInfo.orderCycleStart).format("YYYY-MM-DD")}至${moment(orderInfo.orderCycleEnd).format("YYYY-MM-DD")}`;

    /**请求参数 */
    const Param = {
        appid: AppId,
        mchid: MchId,
        description:desc,
        out_trade_no,//订单号
        amount:{//金额
            total:orderInfo.money * 100 //微信支付的单位是分  金额要乘100
            // total:1
        },
        notify_url:systemConfig.weChartNotifyUrl,//订单回调
    };
    const result = await pay.transactions_native(Param);
    if (result.status != 200) throw new BizError(ERRORENUM.调起微信支付失败);
    let code_url = result.data.code_url;
    let updateInfo = {
        weChartCreatePayMs:new Date().valueOf(),
        weChartPR:out_trade_no, paymentMethod:PAYMENTTYPE.微信支付, weChartState:WEICHARTPAYSTATE.未支付,
        weChartPayUrl:code_url,
    };
    await updateOneData(TABLEENUM.订单表, {id}, updateInfo );
    return {code_url, weChartPR:out_trade_no};
}

async function close(id:string) {
    await updateOneData(TABLEENUM.订单表, {id}, { weChartState:WEICHARTPAYSTATE.未提交, weChartCreatePayMs:0 });
    return {state:WEICHARTPAYSTATE.未提交, msg:"订单已关闭"};
}


/**
 * 订单查询状态【前端调用】
 */
export async function orderState({id, weChartPR}) {
    let orderInfo = await findOnce(TABLEENUM.订单表, {id, weChartPR}, ["id", "state", "weChartCreatePayMs", "weChartState", "confirmReceipt"]);
    if (!orderInfo || !orderInfo.id) throw new BizError(ERRORENUM.订单不存在);
    if (orderInfo.state == ORDERSTATE.已支付 && orderInfo.confirmReceipt != RECEIPTCONFIRMATION.退回) {
        return {state:WEICHARTPAYSTATE.已支付, msg:"已支付"};//已支付
    }
    if (orderInfo.weChartState == WEICHARTPAYSTATE.未支付) {
        if (!orderInfo.weChartCreatePayMs) return {state:WEICHARTPAYSTATE.未提交, msg:"订单未提交"}; 
        if ( (new Date(orderInfo.weChartCreatePayMs).valueOf() +  (15 * 60 * 1000)) > new Date().valueOf() ) {
            const weChartResult = await pay.query({out_trade_no: weChartPR});
            if (weChartResult.status != 200 && weChartResult.status != 204 ) throw new BizError(ERRORENUM.查看微信支付状态失败);
            if (weChartResult.trade_state == 'CLOSED' ) {
                await updateOneData(TABLEENUM.订单表, {id}, { weChartState:WEICHARTPAYSTATE.未提交, weChartCreatePayMs:0 });
                let result = await close(id);
                return result;
            }
        
            return {state:WEICHARTPAYSTATE.未支付, msg:weChartResult.trade_state_desc};

        } else {
            /**超过15分钟主动关闭订单 */
            let result = await close(id);
            return result;
        }
    }
    return {state:WEICHARTPAYSTATE.未提交, msg:"订单未提交"};
}


/**
 * 关闭订单【前端调用】
 */
export async function orderClose({id, weChartPR}) {
    let orderInfo = await findOnce(TABLEENUM.订单表, {id, weChartPR}, ["id"]);
    if (!orderInfo || !orderInfo.id) throw new BizError(ERRORENUM.订单不存在);

    await pay.close(weChartPR);

    await close(id);

    return successResult();
}


/**
 * 微信回调函数【微信用】
 */
export async function payCallback(body) {
    if (body.resource && body.summary == "支付成功") {
        const wechartCallbackData = pay.decipher_gcm(body.resource.ciphertext, body.resource.associated_data, body.resource.nonce, V3Key);
        if (wechartCallbackData.trade_state == "SUCCESS") {
            /**支付成功 */
            let oldInfo = await findOnce(TABLEENUM.订单表, {weChartPR:wechartCallbackData.out_trade_no});
            if (!oldInfo || !oldInfo.id) throw new BizError(ERRORENUM.目标数据不存在);

            //更新订单状态
            let updateInfo:any = {
                paymentNum:wechartCallbackData.transaction_id,
                state:ORDERSTATE.已支付,
                paymentMethod:PAYMENTTYPE.微信支付,
                payTime:new Date().valueOf(),
                weChartState:WEICHARTPAYSTATE.已支付,
                confirmReceipt:RECEIPTCONFIRMATION.收款确认,
                confirmReceiptMs:new Date().valueOf(),
                invoiceStatus:INVOICESTATUS.未开发票
            };

            await updateOneData(TABLEENUM.订单表, {weChartPR:wechartCallbackData.out_trade_no}, updateInfo);

            //更新用户状态
            let notPayCount = await findCount(TABLEENUM.订单表, {userId:oldInfo.userId, state:ORDERSTATE.未支付} );

            /**只有一笔欠费时才更新用户状态 */
            let updateUserInfo:any = {};
            if (notPayCount < 1) {
                let newOrderInfo = await findOnceToSort(TABLEENUM.订单表, {userId:oldInfo.userId}, {lifespanEndTime:-1}, ["orderCycleStart","orderCycleEnd"]);
                
                updateUserInfo.lifespanStartTime = newOrderInfo.orderCycleStart,
                updateUserInfo.lifespanEndTime = newOrderInfo.orderCycleEnd,
                updateUserInfo.isGracePeriod = STATE.否,
                updateUserInfo.gracePeriodEndTime = 0,
                updateUserInfo.memberState = MEMBERSTATE.正常,
                updateUserInfo.paymentStatus = PAYMENTSTATUS.已支付
            } else {//非一笔订单 要更新会员到期时间 到 用户表
                updateUserInfo.lifespanStartTime = oldInfo.orderCycleStart;
                updateUserInfo.lifespanEndTime = oldInfo.orderCycleEnd;
            }
            if (oldInfo.isFirst) {
                updateUserInfo.isFirstPay = true;
            }
            if (Object.keys(updateUserInfo).length) await updateOneData(TABLEENUM.用户表, {userId:oldInfo.userId}, updateUserInfo);
            
            //添加审批日志
            let addLogInfo = {
                orderId:oldInfo.id,
                operationTime:new Date().valueOf(),
                operationBehavior:ORDEREXAMINE.用户提交,
                remarks:"微信付款"
            };
            await addOneData(TABLEENUM.订单审批历史表, addLogInfo );

            return {
                code:"SUCCESS",
                message:"成功"
            }
        } else {
            await pay.close(wechartCallbackData.out_trade_no);
            await updateOneData(TABLEENUM.订单表, {weChartPR:wechartCallbackData.out_trade_no}, { weChartState:WEICHARTPAYSTATE.未提交, weChartCreatePayMs:0 });
            throw new BizError(ERRORENUM.支付失败, wechartCallbackData.trade_state_desc);
        }
    } else {
        throw new BizError(ERRORENUM.微信支付回调错误, body.summary);
    }
}