/**
 * 财务管理-待开发票
 * 财务管理-已开发票
 */

import moment = require("moment");
import { INVOICESTATUS, ISPAYENUM, MEMBERLEVEL, MEMBERSTATE, MEMBERTYPE, ORDEREXAMINE, ORDERSTATE, PAYMENTTYPE, RECEIPTCONFIRMATION } from "../../../config/enum";
import { TABLEENUM } from "../../../data/models/model";
import { find, findCount, findOnce, findToPage } from "../../../data/select";
import { extractData } from "../../../util/piecemeal";
import { changeEnumValue, eccEnumValue } from "../../../util/verificationEnum";
import { ERRORENUM } from "../../../config/errorEnum";
import { BizError } from "../../../util/bizError";
import { updateOneData } from "../../../data/update";
import { addOneData } from "../../../data/add";
import { successResult } from "../../../tools/system";


/**
 * 发票管理-待开发票 success
 * @param name 名称关键字：个人会员匹配真实姓名，单位会员匹配单位名称
 * @param memberType 会员类别 unitMemberType、individualMemberType  多选
 * 会员类别：个人【个人会员、专业会员】单位【院校、机构、其他】返回前端枚举：MEMBERTYPEECCENUM
 * @param documentId 身份证
 * @param phone 登录手机号
 * @param mail 单位/个人邮箱
 * @param joinStartTime 入会开始时间
 * @param joinEndTime 入会结束时间
 * @param memberLevel 会员级别/职务 多选
 * 会员级别/职务：【普通会员、理事会员、常务理事会员】
 * @param paymentType 支付方式
 * @param isPay 是否支付
 * @param weChartPR 微信订单号
 * @param pageNumber 当前页
 */
export async function billStateList({name, memberType, documentId, phone, mail, joinStartTime, joinEndTime, memberLevel, paymentType, isPay, weChartPR, pageNumber}) {
    eccEnumValue("发票列表", "是否支付", ISPAYENUM, isPay );
    let findParam:any = { 
        invoiceStatus:INVOICESTATUS.未开发票
    };

    /**用户表查询条件 */
    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 (isSelectUser) {
        let checkUserIdDataList = await find(TABLEENUM.用户表, itemParam, ["userId"]);
        checkUserIdDataList.forEach(key => {
            checkUserIdList.push(key.userId); 
        });
    }
    if (checkUserIdList.length) {
        findParam.userId = {"$in":checkUserIdList}
    }

    if (phone) findParam.phone = phone;
    if (paymentType) {
        eccEnumValue("发票列表", "支付类型", PAYMENTTYPE, paymentType);
        findParam.paymentMethod = paymentType;
    }
    if (isPay) findParam.state = isPay;
    if (weChartPR) findParam.paymentNum = {"$regex":`${weChartPR}`};

    let selectFile = ["id", "unitName", "orderCycleStart", "orderCycleEnd", "money", "paymentMethod", "memberCategory", "state", "paymentNum", "userId", "desc", "invoiceMail", "weChartCreatePayMs"];
    let dbList = await findToPage(TABLEENUM.订单表, findParam, selectFile, pageNumber);
    let dataCount = await findCount(TABLEENUM.订单表, findParam);

    let dataList = [];

    let itemFile = ["id", "userId", "unitName", "money", "paymentNum", "memberCategory", "state", "paymentMethod", "desc", "invoiceMail", "weChartCreatePayMs"];
    for (let i= 0; i < dbList.length; i++) {
        let info = dbList[i];
        let itemData:any = extractData(info, itemFile);
        if (!itemData.desc) itemData.desc = "";
        if (!itemData.invoiceMail) itemData.invoiceMail = "";
        itemData.joinTime = moment(info.orderCycleStart).format("YYYY-MM-DD");
        itemData.memberType = changeEnumValue(MEMBERTYPE, itemData.memberCategory);
        itemData.paymentMethod = changeEnumValue(PAYMENTTYPE, itemData.paymentMethod);
        itemData.isPay = changeEnumValue(ORDERSTATE, itemData.state);
        let userInfomation = await findOnce(TABLEENUM.用户表, {userId:itemData.userId}, ["userId", "memberState", "name"]);
        itemData.memberState = changeEnumValue(MEMBERSTATE, userInfomation.memberState);
        // itemData.cycle = `${moment(info.orderCycleStart).format("YYYY-MM-DD")}至${moment(info.orderCycleEnd).format("YYYY-MM-DD")}`;
        itemData.cycle = `${moment(info.orderCycleStart).format("YYYY")}至${moment(info.orderCycleEnd).format("YYYY")}`;
        itemData.weChartCreatePayMs = moment(info.weChartCreatePayMs || info.payTime).format("YYYY-MM-DD");
        itemData.name = userInfomation.name;
        dataList.push(itemData);
    }

    return {dataList, dataCount};
}



/**
 * 发票管理-财务核对页面-审批历史
 * @param param0 
 * @returns 
 */
export async function confirmReceiptHistory({id}) {
    let dbList = await find(TABLEENUM.订单审批历史表, {orderId:id});

    let dataList = [];
    dbList.sort((a, b) => {return b.operationTime- a.operationTime});
    dbList.forEach(info => {
        let item:any = extractData(info, ["operationTime", "operationBehavior", "remarks", "refundImgUrl"]);
        item.operationTime = moment(item.operationTime).format("YYYY-MM-DD HH:mm:SS");
        item.operationBehavior = changeEnumValue(ORDEREXAMINE, item.operationBehavior);
        dataList.push(item);
    });

    return {dataList};
}



/**
 * 上传发票 success
 * @param param0 
 */
export async function upInvoice({id, invoiceUrl}) {
    let orderInfo = await findOnce(TABLEENUM.订单表, {id});

    if (!orderInfo || !orderInfo.id) throw new BizError(ERRORENUM.目标数据不存在);
    if (orderInfo.invoiceStatus != INVOICESTATUS.未开发票 && orderInfo.invoiceStatus != INVOICESTATUS.已开发票 ) throw new BizError(ERRORENUM.订单状态无法开具发票, `${orderInfo.id}无法开具发票，因为发票状态为${orderInfo.invoiceStatus}`);
    
    let updateInfo = {
        invoiceStatus : INVOICESTATUS.已开发票,
        // invoiceAdd:invoiceUrl
    };
    await updateOneData(TABLEENUM.订单表, {id}, updateInfo);

    //添加日志
    let addLogInfo = {
        orderId:id,
        operationTime:new Date().valueOf(),
        operationBehavior:ORDEREXAMINE.已开票,
        isReceiveMoney:true,
        remarks:``
    };
    await addOneData(TABLEENUM.订单审批历史表, addLogInfo );

    return successResult();
}


/**
 * 退回发票 success
 * @param param0 
 */
export async function backInvoice({id}) {
    let orderInfo = await findOnce(TABLEENUM.订单表, {id});

    if (!orderInfo || !orderInfo.id) throw new BizError(ERRORENUM.目标数据不存在);
    if (orderInfo.invoiceStatus != INVOICESTATUS.未开发票) throw new BizError(ERRORENUM.订单状态无法开具发票, `${orderInfo.id}无法开具发票，因为发票状态为${orderInfo.invoiceStatus}`);

    if (orderInfo.paymentMethod == PAYMENTTYPE.微信支付) throw new BizError(ERRORENUM.微信支付无法退回发票请求);

    let updateInfo:any = {
        invoiceStatus : INVOICESTATUS.退回,
        advanceInvoice:false,
    };
    if (orderInfo.state == ORDERSTATE.已支付 ) updateInfo.confirmReceipt = RECEIPTCONFIRMATION.待确认
    await updateOneData(TABLEENUM.订单表, {id}, updateInfo);
    
    return successResult();
}


/**
 * 发票管理-待开发票-数据导出
 * @param param0 
 */
 export async function outPutBillState({exportColumns}) {
    let findParam:any = { 
        invoiceStatus:INVOICESTATUS.未开发票
    };

    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", "confirmReceiptMs", "payTime"];
    let dbList = await find(TABLEENUM.订单表, findParam, selectFile);
    let timeChnageList = ["orderCycleStart", "operationTime", "confirmReceiptMs", "payTime"];
    let memberChnageList = ["name", "card", "mail"];

    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", "unitName", "documentId", "uscc", "mail", "unitMail", "memberLevel", "phone"]);
        let subList = [];
        for (let i = 0; i < selectConf.length; i++) {
            let key = selectConf[i];
            let value = info[key] || "";
            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") {
                if (info.memberCategory == MEMBERTYPE.个人会员) value = userInfo.mail;
                else if (info.memberCategory == MEMBERTYPE.单位会员) value = userInfo.unitMail;
            }
            if (key == "paymentMethod" || key == "paymentNum") {
                if (!info.paymentMethod) {
                    value = "-";
                }
            }
            if (key == "orderCycle") value = `${moment(info.orderCycleStart).format("YYYY-MM-DD")}至${moment(info.orderCycleEnd).format("YYYY-MM-DD")}`;
            // if (key == "payTime") {
            //     if (info.paymentMethod != PAYMENTTYPE.微信支付) value = "-"
            // }
            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);
            }
            subList.push(value);
        }
        dataList.push(subList);
    }

    return {dataList};
}


/**
 * 发票管理-待开发票-审批历史 todo
 * @param param0 
 * @returns 
 */
export async function billStateHistory({id}) {
    let dbList = await find(TABLEENUM.订单审批历史表, {orderId:id});

    let dataList = [];
    dbList.sort((a, b) => {return b.operationTime- a.operationTime});
    dbList.forEach(info => {
        let item:any = extractData(info, ["operationTime", "operationBehavior", "remarks", "refundImgUrl"]);
        item.operationTime = moment(item.operationTime).format("YYYY-MM-DD HH:mm:SS");
        item.operationBehavior = changeEnumValue(ORDEREXAMINE, item.operationBehavior);
        dataList.push(item);
    });

    return {dataList};
}


/**
 * 批量开票确认
 * @param param0 
 */
export async function billStateBatchAdopt({idList}) {
    //限制长度
    if (idList.length > 10) throw new BizError(ERRORENUM.批量操作超过个数限制);

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

    for (let i = 0; i < idList.length; i++) {
        let id = idList[i];
        if (!id) continue;//空id跳过

        let orderInfo = await findOnce(TABLEENUM.订单表, {id});

        if (!orderInfo || !orderInfo.id) throw new BizError(ERRORENUM.目标数据不存在);
        if (orderInfo.invoiceStatus != INVOICESTATUS.未开发票 && orderInfo.invoiceStatus != INVOICESTATUS.已开发票 ) throw new BizError(ERRORENUM.订单状态无法开具发票, `${orderInfo.id}无法开具发票，因为发票状态为${orderInfo.invoiceStatus}`);
        
        let updateInfo = {
            invoiceStatus : INVOICESTATUS.已开发票,
            // invoiceAdd:invoiceUrl
        };
        await updateOneData(TABLEENUM.订单表, {id}, updateInfo);
    }

    return successResult();
}


/**
 * 发票管理-已开发票 success
 * @param name 名称关键字：个人会员匹配真实姓名，单位会员匹配单位名称
 * @param memberType 会员类别 unitMemberType、individualMemberType  多选
 * 会员类别：个人【个人会员、专业会员】单位【院校、机构、其他】返回前端枚举：MEMBERTYPEECCENUM
 * @param documentId 身份证
 * @param phone 登录手机号
 * @param mail 单位/个人邮箱
 * @param joinStartTime 入会开始时间
 * @param joinEndTime 入会结束时间
 * @param memberLevel 会员级别/职务 多选
 * 会员级别/职务：【普通会员、理事会员、常务理事会员】
 * @param paymentType 支付方式
 * @param isPay 是否支付
 * @param pageNumber 当前页
 */
export async function invoicedList({name, memberType, documentId, phone, mail, joinStartTime, joinEndTime, memberLevel, paymentType, isPay, pageNumber}) {
    eccEnumValue("发票列表", "支付类型", PAYMENTTYPE, paymentType);
    eccEnumValue("发票列表", "是否支付", ISPAYENUM, isPay );

    let findParam:any = { 
        invoiceStatus:INVOICESTATUS.已开发票
    };

    /**用户表查询条件 */
    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 (isSelectUser) {
        let checkUserIdDataList = await find(TABLEENUM.用户表, itemParam, ["userId"]);
        checkUserIdDataList.forEach(key => {
            checkUserIdList.push(key.userId); 
        });
    }
    if (checkUserIdList.length) {
        findParam.userId = {"$in":checkUserIdList}
    }
    
    if (phone) findParam.phone = phone;
    if (paymentType) findParam.paymentMethod = paymentType;
    if (isPay) findParam.state = isPay

    let selectFile = ["id", "unitName", "orderCycleStart", "orderCycleEnd", "money", "paymentMethod", "memberCategory", "state", "paymentNum", "userId", "desc"];
    let dbList = await findToPage(TABLEENUM.订单表, findParam, selectFile, pageNumber);
    let dataCount = await findCount(TABLEENUM.订单表, findParam);

    let dataList = [];

    let itemFile = ["id", "unitName", "money", "paymentNum", "state", "userId", "memberCategory", "paymentMethod", "desc"];
    
    for (let i = 0; i < dbList.length; i++) {
        let info = dbList[i];
        let itemData:any = extractData(info, itemFile);
        if (!itemData.desc) itemData.desc = "";
        itemData.joinTime = moment(info.orderCycleStart).format("YYYY-MM-DD");
        itemData.memberType = changeEnumValue(MEMBERTYPE, itemData.memberCategory);
        itemData.paymentMethod = changeEnumValue(PAYMENTTYPE, itemData.paymentMethod);
        itemData.cycle = `${moment(info.orderCycleStart).format("YYYY-MM-DD")}至${moment(info.orderCycleEnd).format("YYYY-MM-DD")}`;
        itemData.isPay = changeEnumValue(ORDERSTATE, itemData.state);
        let userInfo = await findOnce(TABLEENUM.用户表, {userId:itemData.userId}, ["memberState", "name"])
        itemData.memberState = changeEnumValue(MEMBERSTATE, userInfo.memberState);
        itemData.name = userInfo.name;
        dataList.push(itemData);
    }

    return {dataList, dataCount};
}


/**
 * 发票管理-已开发票-数据导出
 * @param param0 
 */
 export async function outPutInvoiced({exportColumns}) {
    let findParam:any = { 
        invoiceStatus:INVOICESTATUS.已开发票
    };

    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", "confirmReceiptMs", "payTime"];
    let dbList = await find(TABLEENUM.订单表, findParam, selectFile);
    let timeChnageList = ["orderCycleStart", "operationTime", "confirmReceiptMs", "payTime"];

    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", "unitName", "documentId", "uscc", "mail", "unitMail", "memberLevel", "phone"]);
        let subList = [];
        for (let i = 0; i < selectConf.length; i++) {
            let key = selectConf[i];
            let value = info[key] || "";
            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") {
                if (info.memberCategory == MEMBERTYPE.个人会员) value = userInfo.mail;
                else if (info.memberCategory == MEMBERTYPE.单位会员) value = userInfo.unitMail;
            }
            if (key == "paymentMethod" || key == "paymentNum") {
                if (!info.paymentMethod) {
                    value = "-";
                }
            }
            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);
            }
            subList.push(value);
        }
        dataList.push(subList);
    }

    return {dataList};
}


/**
 * 发票管理-已开发票-审批历史 todo
 * @param param0 
 * @returns 
 */
export async function invoicedHistory({id}) {
    let dbList = await find(TABLEENUM.订单审批历史表, {orderId:id});

    let dataList = [];
    dbList.sort((a, b) => {return b.operationTime- a.operationTime});
    dbList.forEach(info => {
        let item:any = extractData(info, ["operationTime", "operationBehavior", "remarks", "refundImgUrl"]);
        item.operationTime = moment(item.operationTime).format("YYYY-MM-DD HH:mm:SS");
        item.operationBehavior = changeEnumValue(ORDEREXAMINE, item.operationBehavior);
        dataList.push(item);
    });

    return {dataList};
}
