/**
 * 数据维护 主要逻辑
 * 作者:lxm
 */

import { BUSINESSDATATYPE, DATAMAINTENANCETYPE, ENTERPRISEBUSINESSTYPE, FUHUASTATE, MOVEOUTCAUSE, MOVEOUTCAUSECLIENT, MOVEOUTCAUSENOTCLIENT, MOVEOUTTRACE, MOVEOUTTYPE } from "../../config/enum";
import { ERRORENUM } from "../../config/errorEnum";
import { findEnterpriseByUscc, findEnterpriseCount, findEnterpriseList, findEnterpriseListToPage } from "../../data/enterprise/enterprise";
import { findBusinessDataByParamsToPage, findBusinessDataByTimeAndUscc, findBusinessDataCountByParams } from "../../data/enterprise/quarterTask/businessdata";
import { findReplenishDataByParam, selectOnceRepleishData } from "../../data/enterprise/replenish";
import { BizError } from "../../util/bizError";
import { eccEnumValue } from "../../util/verificationEnum";
import { eccReqParamater } from "../../util/verificationParam";
import * as sysTools from "../../tools/system";
import { addDataMaintenanceLog } from "../../data/guanWeiHui/dataMaintenanceLog";


/**
 * 获取迁出管理中的企业列表
 * @param fuHuaQiUscc 孵化器统一信用代码  必填
 * @param enterpriseName 企业名称 非必填
 * @param page 当前页面
 * @returns 
 */
export async function getEnterpriseListToOutputEnterprise(fuHuaQiUscc:string, enterpriseName:string, page:number) {
    /**组合查询条件 */
    let selectParam:any = {state:{"$ne":FUHUASTATE.迁出} };
    if (fuHuaQiUscc) selectParam.fuHuaQiUscc = fuHuaQiUscc;
    if (enterpriseName) selectParam.name = {"$regex":`${enterpriseName}`};

    let enterpriseList = await findEnterpriseListToPage(selectParam, (page - 1) * 10 );
    let dataCount = await findEnterpriseCount(selectParam);
    
    let dataList = [];
    enterpriseList.forEach(info => {
        let {name, uscc} = info;
        dataList.push({
            name, 
            uscc,
            moveOutType:0,// 迁出类型  遵循 MOVEOUTTYPE 的值   ----2.0
            moveOutTrace:0,//迁出去向  遵循 MOVEOUTTRACE 的值   ----2.3
            moveOutCause:[],//迁出原因 遵循 MOVEOUTCAUSE  的值   ----2.0
        });
    });

    return {dataList, count:dataCount, pageCount:Math.ceil(dataCount/10) };
}


/**
 * 批量迁出企业  留痕
 * @param userId 操作人id
 * @param enterpriseList 操作的企业列表
 * @returns 
 */
export async function outputEnterpriseByList(userId:string, enterpriseList) {
    //分页一次只能10条
    if (enterpriseList.length > 10) throw new BizError(ERRORENUM.不合规操作);

    //日志详细描述
    let logStr = "";

    /** 由于接口是内部操作，采用比较激进的做法，逐个迁出并且企业之间无原子性 */
    for (let i = 0; i <enterpriseList.length; i++) {
        let {uscc, moveOutType, moveOutTrace, moveOutCause} = enterpriseList[i];

        /**校验参数 */
        if (!uscc || !moveOutType) throw new BizError(ERRORENUM.缺少关键参数导致修改失败, `uscc:${uscc}, moveOutType:${moveOutType}`);
        eccEnumValue("批量导出企业", `第${i+1}个数据`, MOVEOUTTYPE, moveOutType);

        if (!MOVEOUTTYPE.企业注销) {
            eccReqParamater({moveOutTrace:"Number", moveOutCause:"[Number]" }, {moveOutTrace, moveOutCause} );
            eccEnumValue('修改企业孵化状态', '修改为迁出', MOVEOUTTRACE, moveOutTrace);

            /**根据 不同的迁出类型 校验不同的迁出原因枚举 */
            if (moveOutType == MOVEOUTTYPE.毕业迁出) {
                moveOutCause = [moveOutCause[0]];//非毕业迁出是单选
                eccEnumValue('修改企业孵化状态', '修改为迁出', MOVEOUTCAUSECLIENT, moveOutCause);
            }
            if (moveOutType == MOVEOUTTYPE.非毕业迁出) {
                eccEnumValue('修改企业孵化状态', '修改为迁出', MOVEOUTCAUSENOTCLIENT, moveOutCause);
            }
        } else {
            moveOutTrace = 0;
            moveOutCause = [];
        }

        /**所传入的uscc必须是存在的企业 否则视为违法操作 */
        let enterpriseInfo = await findEnterpriseByUscc(uscc);
        if (!enterpriseInfo || !enterpriseInfo.uscc) {
            throw new BizError(ERRORENUM.不合规操作);
        }

        /**通过校验后开始修改数据 */
        enterpriseInfo.moveOutType = moveOutType;
        enterpriseInfo.moveOutCause = moveOutCause;
        enterpriseInfo.moveOutTrace = moveOutTrace;
        enterpriseInfo.moveOutTime = new Date().valueOf();
        enterpriseInfo.state = FUHUASTATE.迁出;

        /**修改为迁出时，需要把实体的和虚拟的字段清空 */
        enterpriseInfo.virtualCause = null;//虚拟孵化模式
        enterpriseInfo.virtualCauseDes = "";//虚拟孵化原因
        enterpriseInfo.leasedArea = 0;//租赁面积

        await enterpriseInfo.save();
        
        //组合详细操作日志
        logStr += ` ${uscc}|${moveOutType}|${moveOutCause}|${JSON.stringify(moveOutTrace)}; `;
    }

    /**加入日志 */
    if (logStr != "") {
        await addDataMaintenanceLog(DATAMAINTENANCETYPE.迁出管理, userId, "迁出:"+logStr);
    }
    
    return {isSuccess:true};
}


/**
 * 企业经营数据列表
 * 这里接口包含了：季度填报的经营数据 和 企业补录的经营数据
 * @param fuHuaQiUscc 孵化器统一信用代码 必填
 * @param year 数据年度 必填
 * @param quarter 数据季度 必填
 * @param type 类型  1= 补录数据   2= 季度任务填报
 * @param enterpriseName 企业名称 非必填
 * @param page 页
 * @returns 
 */
export async function enterpriseBusinessDataList(fuHuaQiUscc:string, year:number, quarter:number, type:number, enterpriseName:string, page:number) {

    let businessList = [];
    let dataCount = 0;
    /**季度任务填报 和 企业补录 的逻辑不一样  需要区分开 */
    if (type == ENTERPRISEBUSINESSTYPE.季度任务填报) {
        /**查询条件 */
        let selectParam:any = {fuHuaQiUscc, year, quarter, '$or':[{"isSubmit":true}, {"fhqIsSubmit":true}] };
        if (enterpriseName) selectParam.name = {"$regex":`${enterpriseName}`};

        let dataBaseList = await findBusinessDataByParamsToPage(selectParam, (page - 1)*10 );
        dataCount = await findBusinessDataCountByParams(selectParam);

        dataBaseList.forEach(info => {
            let { BI, RD, TXP, name, uscc} = info;
            businessList.push({BI, RD, TXP, name, uscc});
        });
    } else {
        let combinationList = await getCombinationList(fuHuaQiUscc, year, quarter, enterpriseName);
        /**模拟分页 */
        dataCount =combinationList.length;
        businessList = combinationList.slice((page-1)*10, page*10 );
    }

    return {dataList:businessList, count:dataCount, pageCount:Math.ceil(dataCount/10) };
}

/**
 * 获取所有符合条件的企业补录数据
 * @param fuHuaQiUscc 孵化器统一信用代码
 * @param year 年度
 * @param quarter 季度
 * @param enterpriseName 企业名称 
 * @returns 
 */
async function getCombinationList(fuHuaQiUscc:string, year:number, quarter:number, enterpriseName:string) {
    let enterpriseList = await findEnterpriseList({fuHuaQiUscc});

    //结构 {uscc:{uscc, name} } 用于筛选补录数据中的目标数据
    let idMap = {};

    enterpriseList.forEach(info => {
        let {uscc, name} = info;
        if ((enterpriseName && name.indexOf(enterpriseName) > -1) || !enterpriseName) {
            idMap[info.uscc] = {uscc, name};
        }
    });

    //释放企业列表数据
    enterpriseList.splice(0, enterpriseList.length);

    //获取年度和季度下的所有企业的补录数据
    let replenList = await findReplenishDataByParam({year, quarter});

    //目标结果  结构：{uscc:{uscc, name, RD, TXP, BI } }
    let result = {};
    replenList.forEach(info => {
        let {uscc, type, value} = info;

        if (idMap[uscc]) {
            if (!result[uscc]) result[uscc] = {uscc, name:idMap[uscc].name};
            switch(type) {
                case BUSINESSDATATYPE.研发投入: 
                    result[uscc]['RD'] = value;
                break;
                case BUSINESSDATATYPE.纳税: 
                    result[uscc]['TXP'] = value;
                break;
                case BUSINESSDATATYPE.营业收入: 
                    result[uscc]['BI'] = value;
                break;
            }
        }
    });

    //返回 [{uscc, name, RD, TXP, BI }]
    return Object.values(result);
} 


/**
 * 修改企业经营数据
 * 
 * @param userId 操作人员id
 * @param uscc 企业统一信用代码
 * @param RD 研发投入 非必填  如果传入undefined 则不进行修改
 * @param TXP 纳税 非必填  如果传入undefined 则不进行修改
 * @param BI 营业收入 非必填  如果传入undefined 则不进行修改
 * @param year 年度
 * @param quarter 季度
 * @param type 类型 1= 补录数据   2= 季度任务填报
 * @returns 
 */
export async function updateEnterpriseBusinessData(userId:string, uscc:string, RD:number, TXP:number, BI:number, year:number, quarter:number, type:number) {
    //日志
    let logStr = "";

    if (type == ENTERPRISEBUSINESSTYPE.季度任务填报) {
        /**修改企业季度任务填报的经营数据 */
        
        //日志明细
        let subLogStr = "";
        let businessdata = await findBusinessDataByTimeAndUscc(uscc, year, quarter);
        if (BI != undefined) {
            businessdata.BI = BI;
            subLogStr += ` BI:${BI}| `
        }
        if (RD != undefined) {
            businessdata.RD = RD;
            subLogStr += ` RD:${RD}| `
        }
        if (TXP != undefined) {
            businessdata.TXP = TXP;
            subLogStr += ` TXP:${TXP}| `;
        }
        if (subLogStr != "") {
            logStr = `季度任务数据修改内容: ${subLogStr}`;
            await businessdata.save();
        }
        
    } else {
        /**修改企业补录的经营数据 */
        let conf = [
            {subType:BUSINESSDATATYPE.研发投入, key:"RD"},
            {subType:BUSINESSDATATYPE.纳税, key:"TXP"},
            {subType:BUSINESSDATATYPE.营业收入, key:"BI"}
        ];
        let subLogStr = "";
        let data = {RD, TXP, BI};
        for (let i = 0; i < conf.length; i++) {
            let subInfo = conf[i];
            if (data[subInfo.key] == undefined) continue; 
            let dataInfo = await selectOnceRepleishData(uscc, subInfo.subType, year, quarter);
            dataInfo.value = data[subInfo.key];
            subLogStr += `${subInfo.key}:${data[subInfo.key]}| `;
            await dataInfo.save();
        }
        if (subLogStr != "") logStr = `补充经营数据修改内容: ${subLogStr}`; 
    }
    
    //三个数据参数为undefined时 日志为空字符串，无需写入日志
    if (logStr != "") { 
        await addDataMaintenanceLog(DATAMAINTENANCETYPE.迁出管理, userId, logStr);
    }

    return {isSuccess:true};
}


/**
 * 根据企业uscc获取企业列表(列表中只有一个企业)
 * @param uscc 
 * @returns 
 */
export async function getEnterprisePwdList(uscc:string) {
    let dataBaseList = await findEnterpriseList({uscc});

    let dataList = [];
    dataBaseList.forEach(info => {
        let {name, uscc} = info;
        dataList.push({name, uscc});
    });

    return {dataList};
}


/**
 * 重置企业密码
 * @param userId 操作人员的id 
 * @param uscc 企业统一信用代码
 * @returns 
 */
export async function resettingEnterprisePwd(userId:string, uscc:string) {
    let enterpriseInfo = await findEnterpriseByUscc(uscc);
    if (!enterpriseInfo) throw new BizError(ERRORENUM.不合规操作);

    enterpriseInfo.pwd = sysTools.getPwdMd5(enterpriseInfo.uscc, sysTools.md5PwdStr(uscc.slice(uscc.length-6)));
    //将首次登录标识重置  用于给企业重新设置密码
    enterpriseInfo.firstLoginIsChangePwd = false;

    await enterpriseInfo.save();

    await addDataMaintenanceLog(DATAMAINTENANCETYPE.重置企业密码, userId, `重置密码: ${uscc}|${enterpriseInfo.pwd}`);

    return {isSuccess:true};
}