/**
 * 管理后台 -> 数据看板 -> 张江看板 -> 孵化器风险预警
 */

import moment = require("moment");
import { findMonthCount, getLowOccupancyRateForMonthData, statsFuHuaQiMonthDataCount } from "../../../../data/fuHuaQi/monthTask/monthTable";
import { findTaskCountByParamCount, statsFuHuaQiTaskReportingRate } from "../../../../data/fuHuaQi/monthTask/task";
import { findAllFuHuaQiOperationNameMap, findFuHuaQiFilesDataByParam } from "../../../../data/fuHuaQi/fuhuaqi";
import { findBusinessDataByParam } from "../../../../data/fuHuaQi/quarterTask/businessData";
import { statsEnterTeamDataByFHQ } from "../../../../data/enterprise/quarterTask/team";
import { statsFHQHaveEnterpriseCount } from "../../../../data/enterprise/enterprise";


/**
 * 孵化器风险预警 概览
 * @returns 
 */
export async function fuHuaQiWarningOverView() {
    let fuHuaQiNameMap = await findAllFuHuaQiOperationNameMap();
    let dataYear = moment().subtract(1, 'months').year();
    let dataMonth = moment().subtract(1, 'months').month();

    let monthTableDataCount = await statsFuHuaQiMonthDataCount(dataYear, dataMonth);
    let monthTableCount = await findMonthCount({year:dataYear, month:dataMonth, draftLock:true});
    let monthAvg = Math.round(monthTableDataCount/monthTableCount) //平均出租率

    /**填报率 = 三种任务的填报实际填报/三种任务的应填报 */
    let taskCount = await findTaskCountByParamCount({year:dataYear, month:dataMonth});
    let taskSubmitCount = await findTaskCountByParamCount({year:dataYear, month:dataMonth, isSubmit:true}); 
    let taskSubmitRate = Math.round(taskSubmitCount/taskCount*100); //任务填报率

    let lowOccupancyRate = [];//低出租率
    let lowMonthData = await getLowOccupancyRateForMonthData(dataYear, dataMonth);
    lowMonthData.forEach(info => {
        let { fuHuaQiUscc, occupancyRate } = info;
        let name = fuHuaQiNameMap[fuHuaQiUscc];
        lowOccupancyRate.push({name, occupancyRate, uscc:fuHuaQiUscc});
    });


    /** 孵化器的填报率= 填报任务数量/当个月的月度任务总数 */
    let reportingStatsData = await statsFuHuaQiTaskReportingRate(dataYear, dataMonth);
    let taskReportingMap = {};
    reportingStatsData.forEach(info => {
        let { _id, count } = info;
        let {isSubmit, uid} = _id;
        if (!taskReportingMap[uid]) taskReportingMap[uid] = {submit:0, notSubmit:0};
        if (isSubmit) taskReportingMap[uid].submit += count;
        else taskReportingMap[uid].notSubmit += count;
    });
    
    let rankList = [];
    for (let key in taskReportingMap ) {
        let {submit, notSubmit} = taskReportingMap[key];
        let itemReportingRate = Math.round(submit/(submit+notSubmit) *100 );
        rankList.push({name:fuHuaQiNameMap[key], rate:itemReportingRate, uscc:key });
    }
    rankList.sort( (a, b) => {return a.itemReportingRate - b.itemReportingRate});

    let lowReportingRate = rankList.slice(0,5)//低填报率

    let revenueAnomalyCount = await getRevenueAnomalyCount(fuHuaQiNameMap); //营收异常
    let fuHuaQiTPAnomalyCount = await getFuHuaQiTPAnomalyCount(fuHuaQiNameMap);
    let teamAnomalyCount = await getTeamAnomalyCount(fuHuaQiNameMap);

    return {monthAvg, taskSubmitRate, lowReportingRate, lowOccupancyRate, revenueAnomalyCount, fuHuaQiTPAnomalyCount, teamAnomalyCount};
}


/**
 * 营收数据正常/异常
 * 需求1 单价参考 hatchingGround 字段  没有备案场地不报警
 * 需求2 拿hatchingGround里的第一个元素的leasePrice
 * 需求3 incubatedAcreage不存在的话跳过
 * @param page
 */
export async function revenueAnomaly(page:number) {
    let fuHuaQiNameMap = await findAllFuHuaQiOperationNameMap();
    let fuHuaQiAcreList = await findFuHuaQiFilesDataByParam({}, {hatchingGround:1, incubatedAcreage:1, uscc:1});

    let expMap = {};//目标值
    fuHuaQiAcreList.forEach(info => {
        let { hatchingGround, incubatedAcreage, uscc}= info;
        if (hatchingGround && hatchingGround.length) {
            let leasePrice = hatchingGround[0].leasePrice;
            if ( !incubatedAcreage ) return
            expMap[uscc] = Math.round(leasePrice * incubatedAcreage * 3);
        }
    });

    let {declarationQuarter, declarationYear} = getDeclarationTime();

    let businessList = await findBusinessDataByParam({year:declarationYear, quarter:declarationQuarter, draftLock:true});
    let checkList = [];
    businessList.forEach(info => {
        let { fuHuaQiUscc, RR } = info;
        let expCount = expMap[fuHuaQiUscc];
        if (!expCount) return;
        //计算浮动值
        
        let max = Math.round( expCount + (expCount * 0.3) );
        let min = Math.round( expCount - (expCount * 0.3) );
    
        let name = fuHuaQiNameMap[fuHuaQiUscc];

        if (RR > max ) {
            checkList.push({name, RR, bcos:"填报数据高于实际"});
        } else if (RR < min) {
            checkList.push({name, RR, bcos:"填报数据低于实际"});
        }
    });

    let dataList = checkList.splice((page-1)*5, 5);
    let count = checkList.length;
    let pageCount = Math.ceil(count/5);

    return {dataList, count, pageCount};
}

async function getRevenueAnomalyCount(fuHuaQiNameMap) {
    let fuHuaQiAcreList = await findFuHuaQiFilesDataByParam({}, {hatchingGround:1, incubatedAcreage:1, uscc:1});

    let expMap = {};//目标值
    fuHuaQiAcreList.forEach(info => {
        let { hatchingGround, incubatedAcreage, uscc}= info;
        if (hatchingGround && hatchingGround.length) {
            let leasePrice = hatchingGround[0].leasePrice;
            if ( !incubatedAcreage ) return
            expMap[uscc] = Math.round(leasePrice * incubatedAcreage * 3);
        }
    });

    let {declarationQuarter, declarationYear} = getDeclarationTime();

    let businessList = await findBusinessDataByParam({year:declarationYear, quarter:declarationQuarter, draftLock:true});
    let count = 0;
    businessList.forEach(info => {
        let { fuHuaQiUscc, RR } = info;
        let expCount = expMap[fuHuaQiUscc];
        if (!expCount) return;
        //计算浮动值
        
        let max = Math.round( expCount + (expCount * 0.3) );
        let min = Math.round( expCount - (expCount * 0.3) );
    
        let name = fuHuaQiNameMap[fuHuaQiUscc];

        if (RR > max || RR < min) {
            count += 1;
        }
    });

    return count;
}


/**
 * 纳税
 * 统计上个季度是否未填报  
 * 统计上个与上上个是否未填报
 * @param page 
 */
export async function fuHuaQiTPAnomaly(page:number) {
    let fuHuaQiNameMap = await findAllFuHuaQiOperationNameMap();
    let {declarationQuarter, declarationYear} = getDeclarationTime();

    let param = {quarter:declarationQuarter, year:declarationYear, "$or":[
        {draftLock:false},
        {TP:0}
    ] };
    let lastQuarterList = await findBusinessDataByParam(param);
    let dataMap = {};
    lastQuarterList.forEach(info => {
        let {fuHuaQiUscc, draftLock, TP} = info;
        let name = fuHuaQiNameMap[fuHuaQiUscc];
        let bcos = "";
        if (!draftLock) bcos = "上季度未提交";
        else bcos = "提交数据为0"
        dataMap[fuHuaQiUscc] = {name, TP, bcos};
    });
    if ((declarationQuarter - 1) == 0) {
        param.quarter = 4;
        param.year = declarationYear -1;
    } else param.quarter = declarationQuarter -1;

    let longQuarterAgoList = await findBusinessDataByParam(param);
    longQuarterAgoList.forEach(info => {
        let {fuHuaQiUscc} = info;
        if (dataMap[fuHuaQiUscc]) {
            dataMap[fuHuaQiUscc].bcos = "长期0申报";
        }
    });

    let checkList = Object.values(dataMap);

    let dataList = checkList.splice((page-1)*5, 5);
    let count = checkList.length;
    let pageCount = Math.ceil(count/5);

    return {dataList, count, pageCount};
}

async function getFuHuaQiTPAnomalyCount(fuHuaQiNameMap) {
    let {declarationQuarter, declarationYear} = getDeclarationTime();

    let param = {quarter:declarationQuarter, year:declarationYear, "$or":[
        {draftLock:false},
        {TP:0}
    ] };
    let lastQuarterList = await findBusinessDataByParam(param);
    let dataMap = {};
    lastQuarterList.forEach(info => {
        let {fuHuaQiUscc, draftLock, TP} = info;
        let name = fuHuaQiNameMap[fuHuaQiUscc];
        let bcos = "";
        if (!draftLock) bcos = "上季度未提交";
        else bcos = "提交数据为0"
        dataMap[fuHuaQiUscc] = {name, TP, bcos};
    });
    if ((declarationQuarter - 1) == 0) {
        param.quarter = 4;
        param.year = declarationYear -1;
    } else param.quarter = declarationQuarter -1;

    let longQuarterAgoList = await findBusinessDataByParam(param);
    longQuarterAgoList.forEach(info => {
        let {fuHuaQiUscc} = info;
        if (dataMap[fuHuaQiUscc]) {
            dataMap[fuHuaQiUscc].bcos = "长期0申报";
        }
    });

    return Object.values(dataMap).length;
}


/**
 * 团队信息预警
 * @param year 
 * @param month 
 */
export async function teamAnomaly(page:number) {
    let fuHuaQiNameMap = await findAllFuHuaQiOperationNameMap();
    let {declarationQuarter, declarationYear} = getDeclarationTime();
    let memberCountMap = await statsEnterTeamDataByFHQ(declarationYear, declarationQuarter);
    let enterpriseCountMap = await statsFHQHaveEnterpriseCount();
    let checkList = [];
    for (let uscc in enterpriseCountMap) {
        let enterpriseCount = enterpriseCountMap[uscc];
        let memberCount = memberCountMap[uscc] || 0;
        let name = fuHuaQiNameMap[uscc];
        if (memberCount < enterpriseCount) checkList.push({uscc, name, enterpriseCount, memberCount});
    }

    let dataList = checkList.splice((page-1)*5, 5);
    let count = checkList.length;
    let pageCount = Math.ceil(count/5);

    return {count, pageCount, dataList};
}

async function getTeamAnomalyCount(fuHuaQiNameMap) {
    let {declarationQuarter, declarationYear} = getDeclarationTime();
    let memberCountMap = await statsEnterTeamDataByFHQ(declarationYear, declarationQuarter);
    let enterpriseCountMap = await statsFHQHaveEnterpriseCount();
    let checkList = [];
    for (let uscc in enterpriseCountMap) {
        let enterpriseCount = enterpriseCountMap[uscc];
        let memberCount = memberCountMap[uscc] || 0;
        let name = fuHuaQiNameMap[uscc];
        if (memberCount < enterpriseCount) checkList.push({uscc, name, enterpriseCount, memberCount});
    }

    return checkList.length;
}


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};
}
