/**
 * 企业数据申报逻辑
 * 作者:lxm
 * 包括：团队信息申报相关  经营数据申报相关
 * 备注：只有每个季度第一个月才是数据填报月 其他月不允许填报数据
 *       这个季度填报上个季度数据
 */

import moment = require("moment");
import { addManyBusinessData, findBusinessDataByTimeAndUscc, findBusinessDataCountByTime, findNotSubmitBusinessDataByTimeAndUscc } from "../../data/enterprise/businessdata";
import { addManyTeamData, addTeamData, findNotSubmitTeamByUsccAndTime, findTeamByUsccAndTime, findTeamDataCountByTime } from "../../data/enterprise/team";
import { changeEnumValue, eccEnumValue } from "../../util/verificationEnum";
import { ENTERPRISEDECLARATIONTYPE, FUHUASTATE } from "../../config/enum";
import { BizError } from "../../util/bizError";
import { ERRORENUM } from "../../config/errorEnum";
import { eccFormParam } from "../../util/verificationParam";
import { EnterpriseAddTeamDataConfig } from "../../config/eccFormParamConfig";
import { EnterpriseTeamConfig } from "../../config/splitResultConfig";
import { checkChange, extractData } from "../../util/piecemeal";
import { findEnterpriseByUscc, findEnterpriseList } from "../../data/enterprise/enterprise";
import { logHandle } from "../../util/log";

/** ----------------------------------------------------- 通用方法 start -------------------------------------- */


/**
 * 当前月是不是数据填报月
 * @returns true = 是
 */
function isInTime() {
    let thisMonth = new Date().getMonth() + 1;
    let tipsMonth = [1, 4, 7, 10];
    return tipsMonth.indexOf(thisMonth) > -1
}


/**
 * 获取当前时间的 填报年度 和 填报季度
 * 即：获取上一个季度
 * @returns declarationYear：数据填报年   declarationQuarter：数据填报季度
 */
function getDeclarationTime() {
    let thisYear = new Date().getFullYear();
    let thisQuarter = moment().quarter();//当月填报季度
    if ( (thisQuarter - 1) < 1 ) {
        thisYear = moment().subtract(1, 'years').year();
        thisQuarter = 4;
    } else thisQuarter = thisQuarter - 1;
    return {declarationYear:thisYear, declarationQuarter:thisQuarter};
}


/**
 * 获取季度的中文名称
 * @param quarter 季度 数字
 * @returns 第 N 季度
 */
function getDeclarationChName(quarter:number) {
    let titleStrList = ["","一", "二", "三", "四"];
    let quarterStr = titleStrList[quarter];
    let title = `第${quarterStr}季度`;
    return title;
}

/** ----------------------------------------------------- 通用方法 end -------------------------------------- */


/**
 * 待填报列表
 * 只有每个季度的第一个月才能填报数据 此时数据提示为 距离本次填报结束还有 N 天
 * 非填报月  要提示本季度的填报未开始  即：{当前季度}季度填报未开始
 * @param uscc 企业统一信用代码
 * @returns dataList数据 distanceEnd 提示
 */
export async function todoList(uscc:string) {
    let {declarationQuarter, declarationYear} = getDeclarationTime();

    /**算剩余时间 */
    let thisQuarters = moment().quarter();//当月季度
    let distanceEnd = `${getDeclarationChName(thisQuarters)}季度填报未开始`;//默认提示
    if (isInTime()) {//在填报月份内
        let endTime = moment().endOf('M').valueOf();
        endTime = Math.ceil((endTime - new Date().valueOf())/(24*3600*1000));
        distanceEnd = `距离本次填报结束还有${endTime}天`;
    } else {
        //todo 这里要放开
        // return {dataList:[], distanceEnd};
    }

    let businessDataInfo = await findNotSubmitBusinessDataByTimeAndUscc(uscc, declarationYear, declarationQuarter);
    let teamsDataInfo = await findNotSubmitTeamByUsccAndTime(uscc, declarationYear, declarationQuarter);

    let title = getDeclarationChName(declarationQuarter)

    let dataList = [
        {
            type:changeEnumValue(ENTERPRISEDECLARATIONTYPE, ENTERPRISEDECLARATIONTYPE.经营状况),
            title,
            subTitle:businessDataInfo && businessDataInfo.isUpdate? `${title}经营状况填报` : ''
        },
        {
            type:changeEnumValue(ENTERPRISEDECLARATIONTYPE, ENTERPRISEDECLARATIONTYPE.团队信息),
            title,
            subTitle:teamsDataInfo && teamsDataInfo.isUpdate? `${title}团队信息填报` : ''
        }
    ];

    

    return {dataList, distanceEnd};
}


/**
 * 已办列表
 * @param uscc 企业统一信用代码
 * @param year 年度
 * @param quarter 季度
 * @returns dataList数据 distanceEnd 提示
 */
export async function completedList(uscc:string, year:number, quarter:number) {
    let {declarationQuarter, declarationYear} = getDeclarationTime();

    //是否可编辑  如果是本月的，就可以编辑
    let modifiable = (isInTime() && declarationQuarter == quarter && declarationYear == year);
    
    let businessDataInfo = await findBusinessDataByTimeAndUscc(uscc, year, quarter);
    let teamsDataInfo = await findTeamByUsccAndTime(uscc, year, quarter);

    let dataList = [];
    let title = getDeclarationChName(quarter);
    
    
    if (businessDataInfo && businessDataInfo.isSubmit) {
        dataList.push({
            type:changeEnumValue(ENTERPRISEDECLARATIONTYPE, ENTERPRISEDECLARATIONTYPE.经营状况),
            title,
            subTitle:`${title}经营状况填报`
        });
    }
    if (teamsDataInfo && teamsDataInfo.isSubmit) {
        dataList.push(
            {
                type:changeEnumValue(ENTERPRISEDECLARATIONTYPE, ENTERPRISEDECLARATIONTYPE.团队信息),
                title,
                subTitle:`${title}团队信息填报`
            }
        );
    }

    return {dataList, modifiable};
}


/**
 * 申报经营数据
 * @param uscc 企业统一信用代码
 * @param BI 营业收入
 * @param RD 研发投入
 * @param TXP 纳税
 */
export async function addBusinessData(uscc:string, BI:number, RD:number, TXP:number) {
    //todo  测试注释 后续要放开
    //if(!isInTime()) throw new BizError(ERRORENUM.不在填报范围之内, `${uscc}不在时间范围内提交申报`);

    let {declarationQuarter, declarationYear} = getDeclarationTime();
    
    let businessDataInfo = await findBusinessDataByTimeAndUscc(uscc, declarationYear, declarationQuarter);
    if (businessDataInfo.isSubmit || businessDataInfo.fhqIsSubmit) throw new BizError(ERRORENUM.请勿重复提交填报数据, `${uscc}已经提交了后点击创建企业经营数据`);
    if (businessDataInfo.isUpdate ) throw new BizError(ERRORENUM.不能重复创建填报, `${uscc}不能重复创建填报 经营数据`);

    businessDataInfo.BI = BI;
    businessDataInfo.RD = RD;
    businessDataInfo.TXP = TXP;
    businessDataInfo.isUpdate = true;

    await businessDataInfo.save();
    
    return {isSuccess:true};
}


/**
 * 修改经营数据
 * @param uscc 企业统一信用代码
 * @param BI 营业收入
 * @param RD 研发投入
 * @param TXP 纳税
 */
export async function updateBusinessData(uscc:string, BI:number, RD:number, TXP:number) {
    //todo  测试注释 后续要放开
    // if(!isInTime()) throw new BizError(ERRORENUM.不在填报范围之内, `${uscc}不在时间范围内提交申报`);

    let {declarationQuarter, declarationYear} = getDeclarationTime();

    let businessDataInfo = await findBusinessDataByTimeAndUscc(uscc, declarationYear, declarationQuarter);
    if (!businessDataInfo.isUpdate) throw new BizError(ERRORENUM.请先创建填报数据, `${uscc}修改经营数据前库里并没有创建数据`);

    businessDataInfo.BI = BI;
    businessDataInfo.RD = RD;
    businessDataInfo.TXP = TXP;

    await businessDataInfo.save();

    return {isSuccess:true};
}


/**
 * 获取经营数据
 * 回显
 * 不能在填报时间外调用
 * @param uscc 企业统一信用代码
 */
export async function businessInfo(uscc:string) {
    //todo 测试注释 后续要放开
    // if (!isInTime()) throw new BizError(ERRORENUM.不在填报范围之内, `${uscc}进行了违规操作`, '在非填报时间调用了回显接口');

    let {declarationQuarter, declarationYear} = getDeclarationTime();

    let businessDataInfo = await findBusinessDataByTimeAndUscc(uscc, declarationYear, declarationQuarter);
    if (!businessDataInfo || !businessDataInfo.year) throw new BizError(ERRORENUM.未提交填报数据, `${uscc}进行了违规操作`, '未提交数据就调用了回显接口');

    let result = {
        BI:businessDataInfo.BI,
        RD:businessDataInfo.RD,
        TXP:businessDataInfo.TXP,
    };

    return result;
}


/**
 * 企业申报团队信息数据
 * @param uscc 企业统一信用代码
 * @param form 表单
 */
export async function addTeamInfo(uscc:string, form) {
    //todo  测试注释 后续要放开
    // if(!isInTime()) throw new BizError(ERRORENUM.不在填报范围之内, `${uscc}不在时间范围内提交申报`);
    eccFormParam("企业申报团队信息数据", EnterpriseAddTeamDataConfig, form);

    let {declarationQuarter, declarationYear} = getDeclarationTime();

    let teamInfo = await findTeamByUsccAndTime(uscc, declarationYear, declarationQuarter);
    if (teamInfo.isSubmit || teamInfo.fhqIsSubmit) throw new BizError(ERRORENUM.请勿重复提交填报数据, `${uscc}已经提交了后点击企业申报团队数据`);
    if (teamInfo.isUpdate ) throw new BizError(ERRORENUM.不能重复创建填报, `${uscc}不能重复创建填报 团队数据`);

    teamInfo.doctor = form.doctor || 0;
    teamInfo.master = form.master || 0;
    teamInfo.undergraduate = form.undergraduate || 0;
    teamInfo.juniorCollege = form.juniorCollege || 0;
    teamInfo.other = form.other || 0;
    teamInfo.studyAbroad = form.studyAbroad || 0;
    teamInfo.graduates = form.graduates || 0;
    teamInfo.createMs = new Date().valueOf();
    teamInfo.isUpdate = true;

    await teamInfo.save();

    return {isSuccess:true};
}


/**
 * 获取团队数据
 * 回显
 * 不能在填报时间外调用
 * @param uscc 企业统一信用代码
 */
export async function getTeamInfo(uscc:string) {
    //todo 测试注释 后续要放开
    // if (!isInTime()) throw new BizError(ERRORENUM.不在填报范围之内, `${uscc}进行了违规操作`, '在非填报时间调用了回显接口');

    let {declarationQuarter, declarationYear} = getDeclarationTime();

    let teamInfo = await findTeamByUsccAndTime(uscc, declarationYear, declarationQuarter);
    if (!teamInfo || !teamInfo.year) throw new BizError(ERRORENUM.未提交填报数据, `${uscc}进行了违规操作`, '未提交数据就调用了回显接口');

    let result = extractData(EnterpriseTeamConfig, teamInfo, false);

    return result;
}


/**
 * 点击查看获取团队数据
 * @param uscc 企业统一信用代码
 */
export async function showTeamInfo(uscc:string) {

    let {declarationQuarter, declarationYear} = getDeclarationTime();

    let teamInfo = await findTeamByUsccAndTime(uscc, declarationYear, declarationQuarter);
    if (!teamInfo || !teamInfo.year) {
        teamInfo = { 
            doctor:0, master:0, undergraduate:0, juniorCollege:0,
            other:0, studyAbroad:0, graduates:0,
        }
    }
    

    let result = extractData(EnterpriseTeamConfig, teamInfo, false);

    return result;
}


/**
 * 企业修改团队信息数据
 * @param uscc 企业统一信用代码
 * @param form 团队信息表单
 */
export async function updateTeamInfo(uscc:string, form) {
    //todo  测试注释 后续要放开
    // if(!isInTime()) throw new BizError(ERRORENUM.不在填报范围之内, `${uscc}不在时间范围内提交申报`);
    eccFormParam("企业修改团队信息数据", EnterpriseAddTeamDataConfig, form);

    let {declarationQuarter, declarationYear} = getDeclarationTime();

    let teamInfo = await findTeamByUsccAndTime(uscc, declarationYear, declarationQuarter);
    if (!teamInfo.isUpdate) throw new BizError(ERRORENUM.请先创建填报数据, `${uscc}修改团队信息数据前库里并没有创建数据`);

    teamInfo.doctor = form.doctor || 0;
    teamInfo.master = form.master || 0;
    teamInfo.undergraduate = form.undergraduate || 0;
    teamInfo.juniorCollege = form.juniorCollege || 0;
    teamInfo.other = form.other || 0;
    teamInfo.studyAbroad = form.studyAbroad || 0;
    teamInfo.graduates = form.graduates || 0;

    await teamInfo.save();

    return {isSuccess:true};
}


/**
 * 提交数据申报
 * @param uscc 企业统一信用代码
 * @param type 提交类型 参考 ENTERPRISEDECLARATIONTYPE
 */
export async function submit(uscc:string, type:number) {
    eccEnumValue("企业提交数据申报", "type", ENTERPRISEDECLARATIONTYPE, type);
    //todo 测试注释 后续要放开
    // if(!isInTime()) throw new BizError(ERRORENUM.不在填报范围之内, `${uscc}不在时间范围内提交申报`);
    
    let {declarationQuarter, declarationYear} = getDeclarationTime();

    let dataInfo;
    if (type == ENTERPRISEDECLARATIONTYPE.团队信息) {
        dataInfo = await findTeamByUsccAndTime(uscc, declarationYear, declarationQuarter);
    } else {
        dataInfo = await findBusinessDataByTimeAndUscc(uscc, declarationYear, declarationQuarter);
    }
    if (!dataInfo || !dataInfo.year) throw new BizError(ERRORENUM.未提交填报数据不能修改, `${uscc}修改前库里并没有创建数据`);

    dataInfo.isSubmit = true;

    await dataInfo.save();

    return {isSuccess:true};
}


/**
 * 下发企业任务
 */
export async function dataDeclarationTask() {
    let {declarationQuarter, declarationYear} = getDeclarationTime();

    let teamDataCount = await findTeamDataCountByTime(declarationYear, declarationQuarter);
    let businessDataCount = await findBusinessDataCountByTime(declarationYear, declarationQuarter);

    if (teamDataCount >0 && businessDataCount > 0) return;

    let enterpriseList = await findEnterpriseList({state:{"$ne":FUHUASTATE.迁出} });
    let businessList = [];
    let teamList = [];
    enterpriseList.forEach(info => {
        let {fuHuaQiUscc, uscc, name} = info;
        let isSubmit = false;
        let fhqIsSubmit = false;
        let isUpdate = false;
        let businessInfo = {
            year:declarationYear,
            fuHuaQiUscc, uscc, name,
            quarter:declarationQuarter, 
            BI:0, RD:0, TXP:0, createTime:0,
            isSubmit, fhqIsSubmit, isUpdate
        };
        businessList.push(businessInfo);
        let teamInfo = {
            fuHuaQiUscc, uscc, name,
            year:declarationYear, quarter:declarationQuarter,  
            doctor:0, master:0, undergraduate:0, juniorCollege:0, other:0, studyAbroad:0, graduates:0,
            createMs:0,
            isSubmit, fhqIsSubmit, isUpdate
        };
        teamList.push(teamInfo);
    });
    
    /**发放任务 */
    if (businessDataCount == 0 ) await addManyBusinessData(businessList);
    logHandle(`添加了${businessList.length} 经营数据任务`);
    if (teamDataCount == 0 ) await addManyTeamData(teamList);
    logHandle(`添加了${teamList.length} 团队数据任务`);
}
