/**
 * 财务管理-费用核对
 */

import moment = require("moment");
import { COSTTYPE, INVOICESTATUS, ISRECEIVE, MAILTYPE, MEMBERLEVEL, MEMBERSTATE, MEMBERTYPE, MEMBERTYPEECCENUM, MSGTYPE, ORDEREXAMINE, ORDERSTATE, PAYMENTSTATUS, PAYMENTTYPE, RECEIPTCONFIRMATION, STATE, UNITMEMBERTYPE } from "../../../config/enum";
import { ERRORENUM } from "../../../config/errorEnum";
import { TABLEENUM } from "../../../data/models/model";
import { find, findCount, findOnce, findOnceToSort, findToPage, findToSortToPage } from "../../../data/select";
import { BizError } from "../../../util/bizError";
import { extractData } from "../../../util/piecemeal";
import { changeEnumValue, eccEnumValue } from "../../../util/verificationEnum";
import { updateOneData } from "../../../data/update";
import { addOneData } from "../../../data/add";
import { getEdition, successResult } from "../../../tools/system";
import { systemSendMail } from "../../mail";
import { sendMessage } from "../../sms";


/**
 * 费用核对
 * @param name 名称关键字：个人会员匹配真实姓名，单位会员匹配单位名称
 * @param memberType 会员类别 unitMemberType、individualMemberType  多选
 * 会员类别：个人【个人会员、专业会员】单位【院校、机构、其他】返回前端枚举：MEMBERTYPEECCENUM
 * @param documentId 身份证
 * @param phone 登录手机号
 * @param mail 单位/个人邮箱
 * @param joinStartTime 入会开始时间
 * @param joinEndTime 入会结束时间
 * @param memberLevel 会员级别/职务 多选
 * 会员级别/职务：【普通会员、理事会员、常务理事会员】
//  * @param paymentType 支付方式
 * @param costType 会费类别
 * @param pageNumber 当前页
 */
export async function paidList({name, memberType, documentId, phone, mail, joinStartTime, session, joinEndTime, memberLevel, payType, paymentNum,pageSize, pageNumber, examineState, backgroundUpload}) {
    if (payType != 1 && payType != 2 && payType != 3) throw new BizError(ERRORENUM.参数错误);
    // eccEnumValue("财务核对列表", "会费类别", COSTTYPE, costType );

    let findParam:any = {
        state:ORDERSTATE.已支付
    };

    if (payType == 1) {
        findParam.paymentMethod = PAYMENTTYPE.微信支付;
    } else if (payType == 2) {
        if (backgroundUpload == null) {
            findParam.paymentMethod = {"$ne":PAYMENTTYPE.微信支付};
        } else {
            if (backgroundUpload == STATE.是) findParam.paymentMethod = PAYMENTTYPE.后台上传;
            else if (backgroundUpload == STATE.否) findParam.paymentMethod = PAYMENTTYPE.银行转账;   
        }
    }

    if (examineState) {
        if (examineState == 1) {
            findParam.confirmReceipt = RECEIPTCONFIRMATION.待确认;
        } else {
            findParam.confirmReceipt = RECEIPTCONFIRMATION.收款确认;
        }
    } else findParam.confirmReceipt = {"$ne":RECEIPTCONFIRMATION.退回}

    if (paymentNum) {
        findParam.paymentNum = paymentNum;
    }

    /**用户表查询条件 */
    let checkUserIdList = [];
    let itemParam:any = {};
    let isSelectUser = false;
    if (name) {
        isSelectUser = true;
        itemParam = {
            "$or":[
                {unitName:{"$regex":`${name}`}},
                {name:{"$regex":`${name}`}}
            ]
        }
    }
    if (memberType && memberType.length) {
        isSelectUser = true;
        itemParam["$or"] = [ {unitMemberType:{"$in":memberType}}, {individualMemberType:{"$in":memberType}} ];
    }
    if (documentId) {
        isSelectUser = true;
        itemParam.documentId = documentId;
    }    
    if (mail) {
        isSelectUser = true;
        itemParam.mail = mail;
    }
    if (joinStartTime) {
        isSelectUser = true;
        itemParam["joinTime"] = {"$gt":joinStartTime};
    }
    if (joinEndTime) {
        isSelectUser = true;
        if (!itemParam["joinTime"]) itemParam["joinTime"] = {};
        itemParam["joinTime"]["$lt"] = joinEndTime;
    }
    if (memberLevel && memberLevel.length) {
        isSelectUser = true;
        itemParam.memberLevel = {"$in":memberLevel};
    }
    if (session) {
        isSelectUser = true;
        itemParam.session = session;
    }
    if (phone) {
        isSelectUser = true;
        itemParam.phone = phone;
    }
    if (isSelectUser) {
        let checkUserIdDataList = await find(TABLEENUM.用户表, itemParam, ["userId"]);
        checkUserIdDataList.forEach(key => {
            checkUserIdList.push(key.userId); 
        });
    }
    if (checkUserIdList.length) {
        findParam.userId = {"$in":checkUserIdList}
    }
    
    // if (costType) findParam.isFirst = costType == COSTTYPE.首次;

    let selectFile = ["id", "unitName", "userId", "orderCycleStart", "orderCycleEnd", "money", "paymentMethod", "memberCategory", 
    "isFirst", "payTime", "paymentNum", "memberState", "operationTime", "confirmReceipt", "invoiceStatus" ];
    let dbList = await findToSortToPage(TABLEENUM.订单表, findParam, selectFile, {payTime:-1}, pageNumber, pageSize);
    let dataCount = await findCount(TABLEENUM.订单表, findParam);

    let dataList = [];

    let itemFile = ["id", "unitName", "money", "paymentNum", "userId", "paymentMethod"];
    for ( let i = 0; i < dbList.length; i++) {
        let info = dbList[i];
        let itemData:any = extractData(info, itemFile);
       
        itemData.joinTime = moment(info.orderCycleStart).format("YYYY-MM-DD");
        itemData.operationTime = moment(info.payTime).format("YYYY-MM-DD");
        itemData.memberType = changeEnumValue(MEMBERTYPE, info.memberCategory);
        if (info.memberCategory == MEMBERTYPE.单位会员) {
            let itemMemberInfo = await findOnce(TABLEENUM.用户表, {userId:info.userId}, ["unitMemberType"]);
            itemData.memberType =  changeEnumValue(UNITMEMBERTYPE, itemMemberInfo.unitMemberType);
        }

        itemData.paymentMethod = changeEnumValue(PAYMENTTYPE, info.paymentMethod);
        if (payType == 2) {
            if (info.paymentMethod == PAYMENTTYPE.后台上传) itemData.backgroundUpload = "是";
            if (info.paymentMethod == PAYMENTTYPE.银行转账) itemData.backgroundUpload = "否";
        }

        itemData.costType = info.isFirst == COSTTYPE.首次 ? "首次" : "续费";
        itemData.cycle = `${moment(info.orderCycleStart).format("YYYY")}至${moment(info.orderCycleEnd).format("YYYY")}`

        if (!info.paymentMethod) {
            itemData.paymentMethod = "-";
            itemData.paymentNum = "-";
        }
        
        let userInfo = await findOnce(TABLEENUM.用户表, {userId:info.userId}, ["userId", "memberState", "name", "memberLevel", "individualMemberType", "unitMemberType", "session"]);
        if (!userInfo || !userInfo.userId) continue;
        itemData.memberLevel = changeEnumValue(MEMBERLEVEL, userInfo.memberLevel);
        itemData.name = userInfo.name;
        if(userInfo.individualMemberType) {
            itemData.memberType = changeEnumValue(MEMBERTYPEECCENUM, userInfo.individualMemberType);
        }
        if(userInfo.unitMemberType) {
            itemData.memberType = changeEnumValue(MEMBERTYPEECCENUM, userInfo.unitMemberType);
        }

        itemData.session =  getEdition(parseInt(`${userInfo.session/100}`), parseInt(`${userInfo.session%100}`) );
        itemData.state = info.confirmReceipt == RECEIPTCONFIRMATION.收款确认 ? "已审批" : "待审批";
        itemData.invoiceStatus = info.invoiceStatus == INVOICESTATUS.已开发票 ? "已开" : "未开";
        dataList.push(itemData);
    }

    return {dataList, dataCount};
}



/**
 * 财务核对页-收款确认 success
 * @param id 订单id 
 */
export async function confirmReceiptPass({id}) {
    let orderInfo = await findOnce(TABLEENUM.订单表, {id});
    if (!orderInfo || !orderInfo.id ) throw new BizError(ERRORENUM.目标数据不存在);
    // if (orderInfo.isFirst && !orderInfo.firstPayExamine ) throw new BizError(ERRORENUM.重复提交, '财务核对页-收款确认', `提交通过时订单未通过待支付页的校验`);
    if (orderInfo.confirmReceipt != RECEIPTCONFIRMATION.待确认) throw new BizError(ERRORENUM.重复提交, '发票管理-财务核对页-收款确认', `提交通过时订单已经不是待确认 是${orderInfo.confirmReceipt}`);

    let updateInfo:any = {
        confirmReceipt:RECEIPTCONFIRMATION.收款确认, 
        confirmReceiptMs:new Date().valueOf()
    };
    if (orderInfo.invoiceStatus == INVOICESTATUS.不具备开票条件) updateInfo.invoiceStatus = INVOICESTATUS.未开发票;
    await updateOneData(TABLEENUM.订单表, {id}, updateInfo);

    let notPayCount = await findCount(TABLEENUM.订单表, {userId:orderInfo.userId, state:ORDERSTATE.未支付} );
    let updateUserInfo:any = {};
    /**只有一笔欠费时才更新用户状态 */
    if (notPayCount < 1) {
        let newOrderInfo = await findOnceToSort(TABLEENUM.订单表, {userId:orderInfo.userId}, {orderCycleEnd:-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 = orderInfo.orderCycleStart;
        updateUserInfo.lifespanEndTime = orderInfo.orderCycleEnd;
    }
    
    if (orderInfo.isFirst) {
        updateUserInfo.isFirstPay = true;
    }
    if (Object.keys(updateUserInfo).length) await updateOneData(TABLEENUM.用户表, {userId:orderInfo.userId}, updateUserInfo);
    
    //添加日志
    let addLogInfo = {
        orderId:id,
        operationTime:new Date().valueOf(),
        operationBehavior:ORDEREXAMINE.审核时间,
        isReceiveMoney:true,
        remarks:``
    };
    await addOneData(TABLEENUM.订单审批历史表, addLogInfo );
    
    //发送邮件
    await systemSendMail(orderInfo.userId, MAILTYPE.会员缴费成功后针对线下汇款财务审核通过的时候发送 );

    let userInfo = await findOnce(TABLEENUM.用户表, {userId:orderInfo.userId});
    let smsName = userInfo.memberType == MEMBERTYPE.个人会员 ? userInfo.name : userInfo.unitName;
    sendMessage(userInfo.phone, {name:smsName}, MSGTYPE.会员缴费成功后针对线下汇款财务审核通过的时候发送);

    return successResult();
}


/**
 * 发票管理-财务核对页-收款退回 success
 * @param param0 
 */
export async function confirmReceiptOut({id, isReceive, returnsReasons}) {
    eccEnumValue("收款退回", "是否收到款项", ISRECEIVE, isReceive)
    let orderInfo = await findOnce(TABLEENUM.订单表, {id});
    if (!orderInfo || !orderInfo.id ) throw new BizError(ERRORENUM.目标数据不存在);
    // if (orderInfo.isFirst && !orderInfo.firstPayExamine ) throw new BizError(ERRORENUM.重复提交, '发票管理-财务核对页-收款确认', `提交通过时订单未通过待支付页的校验`);
    if (orderInfo.confirmReceipt != RECEIPTCONFIRMATION.待确认) throw new BizError(ERRORENUM.重复提交, '发票管理-财务核对页-收款确认', `提交通过时订单已经不是待确认 是${orderInfo.confirmReceipt}`);
    if (orderInfo.paymentMethod == PAYMENTTYPE.微信支付) throw new BizError(ERRORENUM.微信支付无法被退回);

    let updateInfo:any = {confirmReceipt:RECEIPTCONFIRMATION.退回, returnsReasons, isReceive};
    if (orderInfo.isFirst == true) {
        updateInfo.firstPayExamine = false;
    }

    await updateOneData(TABLEENUM.订单表, {id}, updateInfo);

    //添加日志
    let addLogInfo = {
        orderId:id,
        operationTime:new Date().valueOf(),
        operationBehavior:ORDEREXAMINE.驳回,
        isReceiveMoney:isReceive == ISRECEIVE.未收到款项_xg其他,
        remarks:`${returnsReasons}`,
    };
    await addOneData(TABLEENUM.订单审批历史表, addLogInfo );

    if (isReceive == ISRECEIVE.提供账户_zkh需退款_ykh){
        //发送邮件
        await systemSendMail(orderInfo.userId, MAILTYPE.会员缴费财务驳回需退款 );

        let userInfo = await findOnce(TABLEENUM.用户表, {userId:orderInfo.userId});
        let smsName = userInfo.memberType == MEMBERTYPE.个人会员 ? userInfo.name : userInfo.unitName;
        sendMessage(userInfo.phone, {name:smsName}, MSGTYPE.会员缴费财务驳回需退款);

    } else {
        await systemSendMail(orderInfo.userId, MAILTYPE.会员缴费财务驳回无需退款 );

        let userInfo = await findOnce(TABLEENUM.用户表, {userId:orderInfo.userId});
        let smsName = userInfo.memberType == MEMBERTYPE.个人会员 ? userInfo.name : userInfo.unitName;
        sendMessage(userInfo.phone, {name:smsName}, MSGTYPE.会员缴费财务驳回无需退款);
    }


    return successResult();
}


/**
 * 发票管理-财务费用核对页-数据导出
 * @param param0 
 */
export async function outPutConfirmReceipt({exportColumns, payType, examineState}) {
    let findParam:any = {
        confirmReceipt:RECEIPTCONFIRMATION.待确认,
        state:ORDERSTATE.已支付
    }

    if (payType == 1) {
        findParam.paymentMethod = PAYMENTTYPE.微信支付;
    } else if (payType == 2) {
        findParam.paymentMethod = {"$ne":PAYMENTTYPE.微信支付};
    }

    if (examineState) {
        if (examineState == 1) {
            findParam.confirmReceipt = RECEIPTCONFIRMATION.待确认;
        } else {
            findParam.confirmReceipt = RECEIPTCONFIRMATION.收款确认;
        }
    } else findParam.confirmReceipt = {"$ne":RECEIPTCONFIRMATION.退回}
    
    let selectTitle = ["序号"];
    let selectConf = [];
    exportColumns.forEach( info=> {
        selectTitle.push(info.key);
        selectConf.push(info.value);
    })
    
    let selectFile = ["id", "unitName", "userId", "orderCycleStart", "orderCycleEnd", "money", "paymentMethod", "memberCategory", "paymentNum", "desc", 
    "invoiceMail", "payTime", "confirmReceipt", "invoiceStatus"];
    let dbList = await find(TABLEENUM.订单表, findParam, selectFile);
    let timeChnageList = ["payTime"]; //"orderCycleStart", "operationTime"

    let dataList = [selectTitle];
    for (let i = 0; i < dbList.length; i++) {
        let info = dbList[i];
        let userInfo = await findOnce(TABLEENUM.用户表, {userId:info.userId}, ["memberState", "name", "session", "unitName", "documentId", "uscc", "mail", "memberLevel",  "phone", "individualMemberType", "unitMemberType"]);
        let orderInfo = await findOnceToSort(TABLEENUM.订单审批历史表, {orderId:info.id,operationBehavior:ORDEREXAMINE.用户提交, refundName:null}, {operationTime:-1}, ["operationTime"]);
        let subList = [ (i+1).toString() ];
        for (let i = 0; i < selectConf.length; i++) {
            let key = selectConf[i];
            let value = info[key] || "";
            if (userInfo) {
                if (key == "memberCategory") {
                    if (info.memberCategory == MEMBERTYPE.个人会员) value = changeEnumValue(MEMBERTYPEECCENUM, userInfo.individualMemberType);
                    else if (info.memberCategory == MEMBERTYPE.单位会员) value = changeEnumValue(MEMBERTYPEECCENUM, userInfo.unitMemberType);
                }
                if (key == "name") {
                    if (info.memberCategory == MEMBERTYPE.个人会员) value = userInfo.name;
                    else if (info.memberCategory == MEMBERTYPE.单位会员) value = userInfo.unitName;
                }
                if (key == "card") {
                    if (info.memberCategory == MEMBERTYPE.个人会员) value = userInfo.documentId;
                    else if (info.memberCategory == MEMBERTYPE.单位会员) value = userInfo.uscc;
                }
                if (key == "mail") {
                    value = userInfo.mail;
                }
                
                if (key == "phone") {
                    value = userInfo.phone;
                }
                if (key == "memberLevel") {
                    value = changeEnumValue(MEMBERLEVEL, userInfo.memberLevel);
                }
                if (key == "session") {
                    value = getEdition(Math.floor(userInfo.session/100), userInfo.session%100 );
                }
            }
            
            if (key == "operationTime") {
                if (orderInfo && orderInfo.operationTime) value = moment(orderInfo.operationTime).format("YYYY-MM-DD");
                else value = "-"
            }
            if (key == "paymentMethod" || key == "paymentNum") {
                if (!info.paymentMethod) {
                    value = "-";
                }
            }
            
            if (key == "confirmReceipt") {
                value = value == RECEIPTCONFIRMATION.收款确认 ? "已审批" : "待审批";
            }
            if (key == "orderCycle") value = `${moment(info.orderCycleStart).format("YYYY-MM-DD")}至${moment(info.orderCycleEnd).format("YYYY-MM-DD")}`;  
            if (value && value != "-") {
                if (timeChnageList.indexOf(key) != -1) value = moment(value).format("YYYY-MM-DD");
                // else if (key == "memberCategory") value = changeEnumValue(MEMBERTYPE, value);
                // else if (key == "memberLevel") value = changeEnumValue(MEMBERLEVEL, value);
                else if (key == "paymentMethod") value = changeEnumValue(PAYMENTTYPE, value);
                else if (key == "invoiceStatus") value = changeEnumValue(INVOICESTATUS, value);
            }
            subList.push(value);
        }
        dataList.push(subList);
    }

    return {dataList};
}




/**
 * 发票管理-财务核对页-批量收款确认 success
 * @param id 订单id 
 */
export async function confirmReceiptManyPass({idList}) {
    //限制长度
    if (idList.length > 50) throw new BizError(ERRORENUM.批量操作超过个数限制);

    let thisDate = new Date();
    const NowMs = thisDate.valueOf();

    for (let i = 0; i < idList.length; i++) {
        let id = idList[i];
        let orderInfo = await findOnce(TABLEENUM.订单表, {id});
        if (!orderInfo || !orderInfo.id ) throw new BizError(ERRORENUM.目标数据不存在);
        // if (orderInfo.isFirst && !orderInfo.firstPayExamine ) throw new BizError(ERRORENUM.重复提交, '发票管理-财务核对页-收款确认', `提交通过时订单未通过待支付页的校验`);
        if (orderInfo.confirmReceipt != RECEIPTCONFIRMATION.待确认) throw new BizError(ERRORENUM.重复提交, '发票管理-财务核对页-收款确认', `提交通过时订单已经不是待确认 是${orderInfo.confirmReceipt}`);

        let updateInfo:any = {confirmReceipt:RECEIPTCONFIRMATION.收款确认, confirmReceiptMs:new Date().valueOf()};
        if (orderInfo.invoiceStatus != INVOICESTATUS.已开发票) updateInfo.invoiceStatus = INVOICESTATUS.未开发票;
        await updateOneData(TABLEENUM.订单表, {id}, updateInfo);

        let notPayCount = await findCount(TABLEENUM.订单表, {userId:orderInfo.userId, state:ORDERSTATE.未支付} );
        let updateUserInfo:any = {};
        /**只有一笔欠费时才更新用户状态 */
        if (notPayCount < 1) {
            let newOrderInfo = await findOnceToSort(TABLEENUM.订单表, {userId:orderInfo.userId}, {orderCycleEnd:-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 = orderInfo.orderCycleStart;
            updateUserInfo.lifespanEndTime = orderInfo.orderCycleEnd;
        }
        if (orderInfo.isFirst) {
            updateUserInfo.isFirstPay = true;
        }
        if (Object.keys(updateUserInfo).length) await updateOneData(TABLEENUM.用户表, {userId:orderInfo.userId}, updateUserInfo);
        
        //添加日志
        let addLogInfo = {
            orderId:id,
            operationTime:new Date().valueOf(),
            operationBehavior:ORDEREXAMINE.审核时间,
            isReceiveMoney:true,
            remarks:``
        };
        await addOneData(TABLEENUM.订单审批历史表, addLogInfo );
    }

    return successResult();
    
}
