package com.hz.pm.api.dashboard.manage;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.hz.pm.api.common.model.constant.BizConst;
import com.hz.pm.api.dashboard.constant.ChartTypeEnum;
import com.hz.pm.api.dashboard.constant.DashboardConstant;
import com.hz.pm.api.dashboard.handle.ApplicationHandler;
import com.hz.pm.api.dashboard.handle.ProjectStatusHandler;
import com.hz.pm.api.dashboard.helper.DashboardChartAssembler;
import com.hz.pm.api.dashboard.helper.DashboardHelper;
import com.hz.pm.api.dashboard.model.basic.AnalysisChart;
import com.hz.pm.api.dashboard.model.basic.CompanyProjectCntBO;
import com.hz.pm.api.dashboard.model.basic.ProjectATIISBO;
import com.hz.pm.api.dashboard.model.po.QueryYearPO;
import com.hz.pm.api.dashboard.model.vo.*;
import com.hz.pm.api.gov.model.entity.GovBizProjectApply;
import com.hz.pm.api.gov.model.entity.GovBizProjectBaseinfo;
import com.hz.pm.api.gov.model.entity.GovOperationProjectBaseinfo;
import com.hz.pm.api.gov.service.IGovBizProjectApplyService;
import com.hz.pm.api.gov.service.IGovBizProjectBaseinfoService;
import com.hz.pm.api.gov.service.IGovOperationProjectBaseinfoService;
import com.hz.pm.api.portrait.service.IProjectTagService;
import com.hz.pm.api.projectdeclared.model.entity.Purchase;
import com.hz.pm.api.projectdeclared.service.IPurchaseService;
import com.hz.pm.api.projectlib.model.enumeration.InstTypeEnum;
import com.hz.pm.api.projectlib.model.enumeration.ProjectStatusEnum;
import com.hz.pm.api.projectlib.model.entity.Project;
import com.hz.pm.api.projectlib.model.entity.ProjectDelayApply;
import com.hz.pm.api.projectlib.service.INdProjectDelayApplyService;
import com.hz.pm.api.projectlib.service.IProjectService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ForkJoinPool;
import java.util.stream.Collectors;

/**
 * @author liuxinxin
 * @date 2023/8/2 上午10:39
 */

@Component
@RequiredArgsConstructor
public class DashboardProjectManage {

    private final IProjectService iProjectService;

    private final IGovBizProjectBaseinfoService baseinfoService;

    private final IGovBizProjectApplyService applyService;


    private final IGovOperationProjectBaseinfoService operationBaseService;
    private final INdProjectDelayApplyService iProjectDelayApplyService;
    private final DashboardHelper dashboardHelper;
    private final IPurchaseService iPurchaseService;

    private final ProjectStatusHandler statusHandler;

    private final IProjectTagService projectTagService;

    private final ApplicationHandler applicationHandler;

    public DashboardProjectSummaryVO getProjectSummary(QueryYearPO queryYearPO) {
        // 预算年度
        Integer year = queryYearPO.getYear();
        String regionCode = queryYearPO.getRegionCode();
        List<Project> allProjectWithRepeatList = iProjectService.list(Wrappers.lambdaQuery(Project.class)
                .eq(Objects.nonNull(year), Project::getProjectYear, year)
                .eq(StringUtils.isNotBlank(regionCode), Project::getAreaCode, regionCode)
        );
        List<Project> allProjectList = allProjectWithRepeatList.stream()
                .filter(r -> r.getNewest()).collect(Collectors.toList());

        List<Long> allProjectIdWithRepeatList = allProjectWithRepeatList.stream().map(Project::getId).collect(Collectors.toList());

        // 项目总数
        Integer projectCnt = allProjectList.size();

        // 待立项项目数
        List<Project> toBeApprovedProjectList = allProjectList.stream()
                .filter(r -> ProjectStatusEnum.TO_BE_APPROVED.getCode().equals(r.getStatus()))
                .collect(Collectors.toList());
        Integer toBeApprovedProjectCnt = toBeApprovedProjectList.size();

        // 已立项项目数
        Integer approvedProjectCnt = projectCnt - toBeApprovedProjectCnt;

        // 项目立项率
        Double projectApprovalRate = BigDecimal.valueOf((float) approvedProjectCnt / projectCnt).setScale(2, RoundingMode.HALF_UP).doubleValue();

        // 项目申报总金额
        List<BigDecimal> declareAmountList = allProjectList.stream().map(Project::getDeclareAmount)
                .filter(Objects::nonNull).
                collect(Collectors.toList());
        BigDecimal declareAmountSum = new BigDecimal("0");
        for (BigDecimal declareAmount : declareAmountList) {
            declareAmountSum.add(declareAmount);
        }

        // 项目批复总金额
        List<BigDecimal> approvedTotalInvestmentIncreaseList = allProjectList.stream().map(Project::getApprovedTotalInvestmentIncrease)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        BigDecimal approvedTotalInvestmentIncreaseSum = new BigDecimal("0");
        for (BigDecimal approvedTotalInvestmentIncrease : approvedTotalInvestmentIncreaseList) {
            approvedTotalInvestmentIncreaseSum.add(approvedTotalInvestmentIncrease);
        }

        // 资金核定率
        BigDecimal fundApprovalRate = new BigDecimal("0");
        if (new BigDecimal("0").compareTo(approvedTotalInvestmentIncreaseSum) != 0) {
            fundApprovalRate = declareAmountSum.divide(approvedTotalInvestmentIncreaseSum, 2, RoundingMode.HALF_UP);
        }


        // 项目采购总金额
        BigDecimal projectProcurementTotalAmount = new BigDecimal("0");
        List<Purchase> purchaseList = iPurchaseService.list(Wrappers.lambdaQuery(Purchase.class)
                .in(Purchase::getProjectId, allProjectIdWithRepeatList));
        for (Purchase purchase : purchaseList) {
            BigDecimal transactionAmount = purchase.getTransactionAmount();
            if (Objects.nonNull(transactionAmount)) {
                projectProcurementTotalAmount.add(transactionAmount);
            }
        }

//        项目画像

        // 延期项目数 延期占比
        List<ProjectDelayApply> projectDelayApplyList = iProjectDelayApplyService
                .list(Wrappers.lambdaQuery(ProjectDelayApply.class)
                        .in(ProjectDelayApply::getProjectId, allProjectIdWithRepeatList));
        Map<Long, List<ProjectDelayApply>> projectDelayApplyListMap = projectDelayApplyList.stream().collect(Collectors.groupingBy(ProjectDelayApply::getProjectId));
        Integer delayProjectCnt = projectDelayApplyListMap.keySet().size();
        Double delayProportion = BigDecimal.valueOf((float) delayProjectCnt / projectCnt).setScale(2, RoundingMode.HALF_UP).doubleValue();

        // 项目变更数量 项目变更金额
        List<Project> changedProjectList = new ArrayList<>();
        Map<String, List<Project>> allProjectMap = allProjectWithRepeatList.stream().collect(Collectors.groupingBy(Project::getProjectCode));
        for (String projectCode : allProjectMap.keySet()) {
            List<Project> projectList = allProjectMap.get(projectCode);
            Project newestProject = projectList.stream()
                    .filter(Project::getNewest)
                    .collect(Collectors.toList()).get(0);
            boolean isChanged = false;
            for (Project project : projectList) {
                Boolean newest = project.getNewest();
                boolean isBackReject = project.getIsBackReject();
                if (!newest && isBackReject) {
                    isChanged = true;
                    break;
                }
            }
            if (isChanged) {
                changedProjectList.add(newestProject);
            }
        }
        Integer changedProjectCnt = changedProjectList.size();

        // 项目变更金额
        BigDecimal changedProjectContractAmountSum = new BigDecimal("0");
        for (Project project : changedProjectList) {
            BigDecimal contractAmount = project.getContractAmount();
            if (Objects.nonNull(contractAmount)) {
                changedProjectContractAmountSum.add(contractAmount);
            }
        }

        // 装配返回VO
        DashboardProjectSummaryVO dashboardProjectSummaryVO = new DashboardProjectSummaryVO();
        dashboardProjectSummaryVO.setProjectCnt(projectCnt);
        dashboardProjectSummaryVO.setApprovedProjectCnt(approvedProjectCnt);
        dashboardProjectSummaryVO.setToBeApprovedProjectCnt(toBeApprovedProjectCnt);
        dashboardProjectSummaryVO.setProjectApprovalRate(projectApprovalRate);
        dashboardProjectSummaryVO.setDeclareAmountSum(declareAmountSum);
        dashboardProjectSummaryVO.setApprovedTotalInvestmentIncreaseSum(approvedTotalInvestmentIncreaseSum);

        dashboardProjectSummaryVO.setDelayProjectCnt(delayProjectCnt);
        dashboardProjectSummaryVO.setDelayProportion(delayProportion);
        dashboardProjectSummaryVO.setChangedProjectCnt(changedProjectCnt);
        dashboardProjectSummaryVO.setChangedProjectContractAmountSum(changedProjectContractAmountSum);
        dashboardProjectSummaryVO.setFundApprovalRate(fundApprovalRate);
        return dashboardProjectSummaryVO;
    }

    public DashboardProjectCntSummaryVO getProjectCntSummary(QueryYearPO queryYearPO) {
        // 预算年度
        Integer year = queryYearPO.getYear();
        String regionCode = queryYearPO.getRegionCode();
        List<Project> allProjectList = iProjectService.list(Wrappers.lambdaQuery(Project.class)
                .eq(Project::getNewest, true)
                .eq(Objects.nonNull(year), Project::getProjectYear, year)
                .eq(StringUtils.isNotBlank(regionCode), Project::getAreaCode, regionCode)
        );

        // 单位项目数量TOP5
        List<CompanyProjectCntBO> companyProjectCntTop5List = new ArrayList<>();
        Map<String, List<Project>> buildOrgNameProjectGroupMap = allProjectList.stream()
                .collect(Collectors.groupingBy(Project::getBuildOrgName));
        for (String buildOrgName : buildOrgNameProjectGroupMap.keySet()) {
            List<Project> projectList = buildOrgNameProjectGroupMap.get(buildOrgName);
            CompanyProjectCntBO companyProjectCntBO = new CompanyProjectCntBO();
            companyProjectCntBO.setBuildOrgName(buildOrgName);
            companyProjectCntBO.setProjectCnt(projectList.size());
            companyProjectCntTop5List.add(companyProjectCntBO);
        }
        companyProjectCntTop5List = companyProjectCntTop5List.stream()
                .sorted(Comparator.comparing(CompanyProjectCntBO::getProjectCnt).reversed())
                .collect(Collectors.toList());
        if (companyProjectCntTop5List.size() > 5) {
            companyProjectCntTop5List = companyProjectCntTop5List.subList(0, 5);
        }

        // 项目增补情况
        Map<Integer, List<Project>> isTemporaryAugmentGroupMap = allProjectList.stream()
                .collect(Collectors.groupingBy(Project::getIsTemporaryAugment));
        Map<Integer, String> temporaryAugmentMap = dashboardHelper.getTemporaryAugmentMap();
        AnalysisChart isTemporaryAugmentAnalysisChart = DashboardChartAssembler.buildAnalysisChart(temporaryAugmentMap, isTemporaryAugmentGroupMap
                , ChartTypeEnum.PROJECT_SUPPLEMENTATION_STATUS_CHART);

        // 各类型项目数量
        Map<String, List<Project>> projectTypeGroupMap = allProjectList.stream()
                .collect(Collectors.groupingBy(Project::getProjectType));
        Map<Integer, String> projectTypeMap = dashboardHelper.getTemporaryAugmentMap();
        AnalysisChart projectTypeAnalysisChart = DashboardChartAssembler.buildAnalysisChartString(projectTypeMap, projectTypeGroupMap
                , ChartTypeEnum.EACH_TYPE_QUANTITY_OF_PROJECT_CHART);

        // 各区域项目数量
        Map<String, List<Project>> areaCodeGroupMap = allProjectList.stream()
                .collect(Collectors.groupingBy(Project::getAreaCode));
        Map<String, String> liShuiRegionCodeNameMap = dashboardHelper.getLiShuiRegionCodeNameMap();
        AnalysisChart areaCodeAnalysisChart = DashboardChartAssembler.buildAnalysisChart(liShuiRegionCodeNameMap, areaCodeGroupMap
                , ChartTypeEnum.PROJECTS_NUMBER_IN_EACH_REGION_CHART);

        // 各领域项目数量
        Map<Integer, List<Project>> bizDomainGroupMap = allProjectList.stream()
                .collect(Collectors.groupingBy(Project::getBizDomain));
        Map<Integer, String> bizDomainMap = dashboardHelper.getBizDomainMap();
        AnalysisChart bizDomainAnalysisChart = DashboardChartAssembler.buildAnalysisChart(bizDomainMap, bizDomainGroupMap
                , ChartTypeEnum.PROJECTS_NUMBER_IN_VARIOUS_FIELDS_CHART);

        // 各阶段项目数量
        Map<Integer, List<Project>> projectStateGroupMap = allProjectList.stream()
                .collect(Collectors.groupingBy(Project::getStage));
        AnalysisChart projectStateAnalysisChart = DashboardChartAssembler
                .buildProjectStateAnalysisChart(projectStateGroupMap, ChartTypeEnum.PROJECTS_NUMBER_IN_EACH_STAGE_CHART);

        DashboardProjectCntSummaryVO dashboardProjectCntSummaryVO = new DashboardProjectCntSummaryVO();
        dashboardProjectCntSummaryVO.setCompanyProjectCntTop5List(companyProjectCntTop5List);
        List<AnalysisChart> analysisChartList = new ArrayList<>();
        dashboardProjectCntSummaryVO.setAnalysisChartList(analysisChartList);
        analysisChartList.add(isTemporaryAugmentAnalysisChart);
        analysisChartList.add(projectTypeAnalysisChart);
        analysisChartList.add(bizDomainAnalysisChart);
        analysisChartList.add(areaCodeAnalysisChart);
        analysisChartList.add(projectStateAnalysisChart);
        return dashboardProjectCntSummaryVO;
    }


    public DashboardInvestmentSummaryVO getInvestmentSummary(QueryYearPO queryYearPO) {
        // 预算年度
        Integer year = queryYearPO.getYear();
        String regionCode = queryYearPO.getRegionCode();
        List<Project> allProjectList = iProjectService.list(Wrappers.lambdaQuery(Project.class)
                .eq(Project::getNewest, true)
                .eq(Objects.nonNull(year), Project::getProjectYear, year)
                .eq(StringUtils.isNotBlank(regionCode), Project::getAreaCode, regionCode)
        );

        // 项目预算TOP5
        List<ProjectATIISBO> projectATIISTop5List = allProjectList.stream().filter(r -> Objects.nonNull(r.getApprovedTotalInvestmentIncrease()))
                .map(r -> {
                    ProjectATIISBO projectATIISBO = new ProjectATIISBO();
                    projectATIISBO.setProjectId(r.getId());
                    projectATIISBO.setProjectCode(r.getProjectCode());
                    projectATIISBO.setProjectName(r.getProjectName());
                    projectATIISBO.setApprovedTotalInvestmentIncrease(r.getApprovedTotalInvestmentIncrease());
                    return projectATIISBO;
                }).collect(Collectors.toList());
        projectATIISTop5List = projectATIISTop5List.stream()
                .sorted(Comparator.comparing(ProjectATIISBO::getApprovedTotalInvestmentIncrease)
                        .reversed()).collect(Collectors.toList());
        if (projectATIISTop5List.size() > 5) {
            projectATIISTop5List = projectATIISTop5List.subList(0, 5);
        }

        // 单位预算TOP5
        List<CompanyProjectCntBO> companyProjectATIISTop5List = new ArrayList<>();
        Map<String, List<Project>> buildOrgNameProjectGroupMap = allProjectList.stream()
                .collect(Collectors.groupingBy(Project::getBuildOrgName));
        for (String buildOrgName : buildOrgNameProjectGroupMap.keySet()) {
            List<Project> projectList = buildOrgNameProjectGroupMap.get(buildOrgName);
            CompanyProjectCntBO companyProjectCntBO = new CompanyProjectCntBO();
            companyProjectCntBO.setBuildOrgName(buildOrgName);
            BigDecimal approvedTotalInvestmentIncreaseSum = new BigDecimal("0");
            for (Project project : projectList) {
                BigDecimal approvedTotalInvestmentIncrease = project.getApprovedTotalInvestmentIncrease();
                if (Objects.nonNull(approvedTotalInvestmentIncrease)) {
                    approvedTotalInvestmentIncreaseSum.add(approvedTotalInvestmentIncrease);
                }
            }
            companyProjectCntBO.setApprovedTotalInvestmentIncreaseSum(approvedTotalInvestmentIncreaseSum);
            companyProjectATIISTop5List.add(companyProjectCntBO);
        }
        companyProjectATIISTop5List = companyProjectATIISTop5List.stream()
                .sorted(Comparator.comparing(CompanyProjectCntBO::getApprovedTotalInvestmentIncreaseSum).reversed())
                .collect(Collectors.toList());
        if (companyProjectATIISTop5List.size() > 5) {
            companyProjectATIISTop5List = companyProjectATIISTop5List.subList(0, 5);
        }

        // 各领域项目投资情况
        Map<Integer, List<Project>> bizDomainGroupMap = allProjectList.stream()
                .collect(Collectors.groupingBy(Project::getBizDomain));
        Map<Integer, String> bizDomainMap = dashboardHelper.getBizDomainMap();
        AnalysisChart bizDomainInvestmentAnalysisChart = DashboardChartAssembler.buildInvestmentAnalysisChart(bizDomainMap, bizDomainGroupMap
                , ChartTypeEnum.PROJECTS_INVESTMENT_AMOUNT_IN_VARIOUS_FIELDS_CHART);

        // 各区域项目投资情况
        Map<String, List<Project>> areaCodeGroupMap = allProjectList.stream()
                .collect(Collectors.groupingBy(Project::getAreaCode));
        Map<String, String> liShuiRegionCodeNameMap = dashboardHelper.getLiShuiRegionCodeNameMap();
        AnalysisChart areaCodeInvestmentAnalysisChart = DashboardChartAssembler.buildInvestmentAnalysisChart(liShuiRegionCodeNameMap, areaCodeGroupMap
                , ChartTypeEnum.PROJECTS_INVESTMENT_SITUATION_IN_VARIOUS_REGIONS);

        DashboardInvestmentSummaryVO dashboardInvestmentSummaryVO = new DashboardInvestmentSummaryVO();
        dashboardInvestmentSummaryVO.setCompanyProjectATIISTop5List(companyProjectATIISTop5List);
        dashboardInvestmentSummaryVO.setProjectATIISTop5List(projectATIISTop5List);
        List<AnalysisChart> analysisChartList = new ArrayList<>();
        dashboardInvestmentSummaryVO.setAnalysisChartList(analysisChartList);
        analysisChartList.add(areaCodeInvestmentAnalysisChart);
        analysisChartList.add(bizDomainInvestmentAnalysisChart);
        return dashboardInvestmentSummaryVO;
    }

    /**
     * 驾驶舱-项目画像
     *
     * @param projectCode
     * @return
     */
    public DashboardProjectProtraitVO getProjectPortrait(String projectCode) {
        DashboardProjectProtraitVO res = new DashboardProjectProtraitVO();
        //1.先查询项目
        Project project = iProjectService.getProjectByCode(projectCode);

        GovBizProjectBaseinfo baseInfo = baseinfoService.getOne(Wrappers.lambdaQuery(GovBizProjectBaseinfo.class)
                .eq(GovBizProjectBaseinfo::getBaseProjId, projectCode)
                .last(BizConst.LIMIT_1));

        GovOperationProjectBaseinfo operationBase = operationBaseService.getOne(Wrappers.lambdaQuery(GovOperationProjectBaseinfo.class)
                .eq(GovOperationProjectBaseinfo::getBaseProjId, projectCode)
                .last(BizConst.LIMIT_1));

        GovBizProjectApply apply = applyService.getOne(Wrappers.lambdaQuery(GovBizProjectApply.class)
                .eq(GovBizProjectApply::getBaseProjId, projectCode)
                .last(BizConst.LIMIT_1));

        if (Objects.isNull(project) && Objects.isNull(baseInfo) && Objects.isNull(operationBase)) {
            return res;
        }

        //2.转换项目信息
        if (Objects.nonNull(project)) {
            ProtraitProjectInfoVO projectInfo = BeanUtil.copyProperties(project, ProtraitProjectInfoVO.class);
            projectInfo.setOverdueSituation("即将超期");
            projectInfo.setSafetyInputRate(convertSafetyInputRate(project));
            projectInfo.setStatus(Objects.nonNull(project.getStatus()) ? project.getStatus().toString() : null);
            //3.项目状态情况
            projectInfo.setStatusSituation(generateProjectStatus(project));
            res.setProjectInfo(projectInfo);
        } else if (Objects.nonNull(baseInfo)) {
            ProtraitProjectInfoVO projectInfo = BeanUtil.copyProperties(baseInfo, ProtraitProjectInfoVO.class);
            projectInfo.setOverdueSituation("即将超期");
            projectInfo.setSafetyInputRate("0");
            if (Objects.nonNull(apply)) {
                try {
                    projectInfo.setProjectYear(Integer.valueOf(apply.getBaseProjSetYear()));
                } catch (Exception e) {
                }
                projectInfo.setProjectIntroduction(apply.getBaseProjIntro());
                projectInfo.setBuildCycle(apply.getBaseProjDuration());
                projectInfo.setApprovalAmount(apply.getBaseProjTotalAmount());
            }
            projectInfo.setProjectCode(projectCode);
            projectInfo.setProjectName(baseInfo.getBaseProjName());
            projectInfo.setBuildOrgName(baseInfo.getBaseBuildDeprt());
            projectInfo.setBuildOrgCode(baseInfo.getBaseBuildDeprtDing());
            //3.项目状态情况
            projectInfo.setStatusSituation(generateProjectStatus(baseInfo));
            projectInfo.setStatus(baseInfo.getBaseProjSetProg());
            res.setProjectInfo(projectInfo);
        } else if (Objects.nonNull(operationBase)) {
            ProtraitProjectInfoVO projectInfo = BeanUtil.copyProperties(operationBase, ProtraitProjectInfoVO.class);
            projectInfo.setOverdueSituation("即将超期");
            projectInfo.setSafetyInputRate("0");
            if (Objects.nonNull(apply)) {
                try {
                    projectInfo.setProjectYear(Integer.valueOf(apply.getBaseProjSetYear()));
                } catch (Exception e) {
                }
                projectInfo.setProjectIntroduction(apply.getBaseProjIntro());
                projectInfo.setBuildCycle(apply.getBaseProjDuration());
                projectInfo.setApprovalAmount(apply.getBaseProjTotalAmount());
            }
            projectInfo.setProjectCode(projectCode);
            projectInfo.setProjectName(operationBase.getBaseProjName());
            projectInfo.setBuildOrgName(operationBase.getBaseBuildDeprt());
            projectInfo.setBuildOrgCode(operationBase.getBaseBuildDeprtDing());
            //3.项目状态情况
            projectInfo.setStatusSituation(generateProjectStatus(operationBase));
            projectInfo.setStatus(operationBase.getBaseProjSetProg());
            res.setProjectInfo(projectInfo);
        }


        //4.查询项目特征
        res.setProjectFeatures(projectTagService.getProjectTas(projectCode));

        //5.查询项目产出
        res.setProjectOutput(applicationHandler.generateOutput(projectCode));

        return res;
    }

    /**
     * 计算安全投入
     *
     * @param project
     * @return
     */
    public static String convertSafetyInputRate(Project project) {
        String safetyInputDescribe = project.getSafetyInputDescribe();
        if (org.apache.commons.lang3.StringUtils.isNotBlank(safetyInputDescribe)) {
            try {
                JSONArray array = JSON.parseArray(safetyInputDescribe);
                final Double[] total = {0.0};
                array.forEach(j -> {
                    JSONObject json = JSON.parseObject(JSON.toJSONString(j));
                    Double safetyInputAmount = json.getDouble(DashboardConstant.Protrait.FEILD_SAFETYMONEY);
                    if (Objects.nonNull(safetyInputAmount)) {
                        total[0] += safetyInputAmount;
                    }
                });
                Double totalAmount = total[0];
                //申报金额
                BigDecimal declareAmount = project.getDeclareAmount();
                if (Objects.isNull(declareAmount) || declareAmount.compareTo(BigDecimal.ZERO) == 0) {
                    return DashboardConstant.Protrait.ZREO_PERCEN;
                }
                BigDecimal rate = BigDecimal.valueOf(totalAmount).multiply(BigDecimal.valueOf(100))
                        .divide(declareAmount, BigDecimal.ROUND_CEILING, RoundingMode.HALF_UP)
                        .stripTrailingZeros();
                return rate.toPlainString();
            } catch (Exception e) {
            }
        }
        return DashboardConstant.Protrait.ZREO_PERCEN;
    }

    /**
     * 生成项目 状态流转信息
     *
     * @param project
     * @return
     */
    private List<ProtraitProjectStatusSituationVO> generateProjectStatus(Project project) {
        final List<ProtraitProjectStatusSituationVO> res = Lists.newArrayList();
        //1.计划(单位内部审核)
        res.add(new ProtraitProjectStatusSituationVO());
        //2.申报(项目预审)
        res.add(new ProtraitProjectStatusSituationVO());
        //3.审批(建设方案审批)
        res.add(new ProtraitProjectStatusSituationVO());
        //4.建设(立项后的建设中)
        res.add(new ProtraitProjectStatusSituationVO());
        //5.验收(终验)
        res.add(new ProtraitProjectStatusSituationVO());
        //6.运维(todo: 运维时间还没有)
        res.add(ProtraitProjectStatusSituationVO.builder().statusName(DashboardConstant.Protrait.OPERATION).build());
        //7.绩效
        res.add(new ProtraitProjectStatusSituationVO());
        //8.注销(todo: 还没有注销功能)
        res.add(ProtraitProjectStatusSituationVO.builder().statusName(DashboardConstant.Protrait.LOG_OFF).build());

        CompletableFuture.allOf(
                CompletableFuture.runAsync(() -> {
                    res.set(0, statusHandler.generateApproveStatus(project, DashboardConstant.Protrait.PLAN, InstTypeEnum.UNIT_INNER_AUDIT.getCode()));
                }, ForkJoinPool.commonPool()),
                CompletableFuture.runAsync(() -> {
                    res.set(1, statusHandler.generateApproveStatus(project, DashboardConstant.Protrait.DECLARED, InstTypeEnum.PRELIMINARY_PREVIEW.getCode()));
                }, ForkJoinPool.commonPool()),
                CompletableFuture.runAsync(() -> {
                    res.set(2, statusHandler.generateApproveStatus(project, DashboardConstant.Protrait.APPROVE, InstTypeEnum.CONSTRUCTION_PLAN_REVIEW.getCode()));
                }, ForkJoinPool.commonPool()),
                CompletableFuture.runAsync(() -> {
                    res.set(3, statusHandler.generateStatus(project, DashboardConstant.Protrait.CONSTRUCTION,
                            ProjectStatusEnum.UNDER_CONSTRUCTION.getCode(), ProjectStatusEnum.TO_BE_FINALLY_INSPECTED.getCode()));
                }, ForkJoinPool.commonPool()),
                CompletableFuture.runAsync(() -> {
                    res.set(4, statusHandler.generateApproveStatus(project, DashboardConstant.Protrait.ACCEPT, InstTypeEnum.PROJECT_FINAL_INSPECTION.getCode()));
                }, ForkJoinPool.commonPool()),
                CompletableFuture.runAsync(() -> {
                    res.set(6, statusHandler.generatePerformanceStatus(project));
                }, ForkJoinPool.commonPool())
        ).join();
        return res;
    }

    private List<ProtraitProjectStatusSituationVO> generateProjectStatus(GovBizProjectBaseinfo baseinfo) {
        final List<ProtraitProjectStatusSituationVO> res = Lists.newArrayList();
        //1.计划(单位内部审核)
        res.add(new ProtraitProjectStatusSituationVO(DashboardConstant.Protrait.PLAN, null));
        //2.申报(项目预审)
        res.add(new ProtraitProjectStatusSituationVO(DashboardConstant.Protrait.DECLARED, null));
        //3.审批(建设方案审批)
        res.add(new ProtraitProjectStatusSituationVO(DashboardConstant.Protrait.APPROVE, null));
        //4.建设(立项后的建设中)
        res.add(new ProtraitProjectStatusSituationVO(DashboardConstant.Protrait.CONSTRUCTION, null));
        //5.验收(终验)
        res.add(new ProtraitProjectStatusSituationVO(DashboardConstant.Protrait.ACCEPT,
                Objects.nonNull(baseinfo.getBaseProjSetProg()) && "07".equals(baseinfo.getBaseProjSetProg()) ? baseinfo.getTongTime() : null));
        //6.运维(todo: 运维时间还没有)
        res.add(ProtraitProjectStatusSituationVO.builder().statusName(DashboardConstant.Protrait.OPERATION).build());
        //7.绩效
        res.add(new ProtraitProjectStatusSituationVO(DashboardConstant.Protrait.ACCEPT, null));
        //8.注销(todo: 还没有注销功能)
        res.add(ProtraitProjectStatusSituationVO.builder().statusName(DashboardConstant.Protrait.LOG_OFF).build());
        return res;
    }

    private List<ProtraitProjectStatusSituationVO> generateProjectStatus(GovOperationProjectBaseinfo baseinfo) {
        final List<ProtraitProjectStatusSituationVO> res = Lists.newArrayList();
        //1.计划(单位内部审核)
        res.add(new ProtraitProjectStatusSituationVO(DashboardConstant.Protrait.PLAN, null));
        //2.申报(项目预审)
        res.add(new ProtraitProjectStatusSituationVO(DashboardConstant.Protrait.DECLARED, null));
        //3.审批(建设方案审批)
        res.add(new ProtraitProjectStatusSituationVO(DashboardConstant.Protrait.APPROVE, null));
        //4.建设(立项后的建设中)
        res.add(new ProtraitProjectStatusSituationVO(DashboardConstant.Protrait.CONSTRUCTION, null));
        //5.验收(终验)
        res.add(new ProtraitProjectStatusSituationVO(DashboardConstant.Protrait.ACCEPT,
                Objects.nonNull(baseinfo.getBaseProjSetProg()) && "07".equals(baseinfo.getBaseProjSetProg()) ? baseinfo.getTongTime() : null));
        //6.运维(todo: 运维时间还没有)
        res.add(ProtraitProjectStatusSituationVO.builder().statusName(DashboardConstant.Protrait.OPERATION).build());
        //7.绩效
        res.add(new ProtraitProjectStatusSituationVO(DashboardConstant.Protrait.ACCEPT, null));
        //8.注销(todo: 还没有注销功能)
        res.add(ProtraitProjectStatusSituationVO.builder().statusName(DashboardConstant.Protrait.LOG_OFF).build());
        return res;
    }
}
