package com.artfess.cqlt.manager.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.artfess.base.enums.AnalyseTypeEnum;
import com.artfess.base.enums.FaTargetTypeEnum;
import com.artfess.base.enums.HrTargetTypeEnum;
import com.artfess.base.manager.impl.BaseManagerImpl;
import com.artfess.base.util.BeanUtils;
import com.artfess.base.util.CommonUtil;
import com.artfess.base.util.StringUtil;
import com.artfess.cqlt.dao.QfRzStatisticalDao;
import com.artfess.cqlt.manager.QfEnterpriseInfoManager;
import com.artfess.cqlt.manager.QfRzStatisticalManager;
import com.artfess.cqlt.manager.SysSubjectTargetManager;
import com.artfess.cqlt.model.QfEnterpriseInfo;
import com.artfess.cqlt.model.QfRzStatistical;
import com.artfess.cqlt.model.SysSubjectTarget;
import com.artfess.cqlt.utils.FinancialTimeUtils;
import com.artfess.cqlt.vo.DataInfoVo;
import com.artfess.cqlt.vo.DateReqVo;
import com.artfess.cqlt.vo.FaReportRespVo;
import com.artfess.cqlt.vo.FaTargetRespVo;
import com.artfess.cqlt.vo.ReportReqVo;
import com.artfess.cqlt.vo.ReportVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * 人资-大屏统计宽表 服务实现类
 *
 * @author min.wu
 * @company 阿特菲斯信息技术有限公司
 * @since 2023-03-30
 */
@Slf4j
@Service
public class QfRzStatisticalManagerImpl extends BaseManagerImpl<QfRzStatisticalDao, QfRzStatistical> implements QfRzStatisticalManager {

    @Autowired
    private SysSubjectTargetManager sysSubjectTargetManager;

    @Autowired
    private QfEnterpriseInfoManager enterpriseInfoManager;


    private FinancialTimeUtils financialTimeUtils = new FinancialTimeUtils();

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveData(List<ReportVo> list, DataInfoVo dataInfoVo) {
        if (CollectionUtils.isEmpty(list)) {
            return false;
        }
        // 获取人资所有指标数据
        List<String> businessList = Lists.newArrayList();
        businessList.add("hr");
        List<SysSubjectTarget> targetList = sysSubjectTargetManager.getTargetList(businessList);
        if (CollectionUtils.isEmpty(targetList)) {
            return false;
        }
        //获取境外企业
        Map<String, QfEnterpriseInfo> enterpriseInfoMap = enterpriseInfoManager.getEnterpriseInfoMap(null);

        List<QfRzStatistical> dataList = Lists.newArrayList();
        QueryWrapper<QfRzStatistical> query = new QueryWrapper<>();
        query.eq("year_", dataInfoVo.getYear());
        query.eq("quarter_", dataInfoVo.getQuarter());
        query.eq("month_", dataInfoVo.getMonth());
        List<QfRzStatistical> rzStatisticals = this.baseMapper.selectList(query);
        if (CollectionUtils.isEmpty(rzStatisticals)) {
            targetList.forEach(target -> {
                saveRzStatistical(target, dataList, list, dataInfoVo, enterpriseInfoMap);
            });
        } else {
            Map<String, List<QfRzStatistical>> statisticalMap = rzStatisticals.stream().collect(Collectors.groupingBy(QfRzStatistical::getTargetId));
            targetList.forEach(target -> {
                List<QfRzStatistical> statisticalList = Lists.newArrayList();
                if (statisticalMap.containsKey(target.getId())) {
                    statisticalList = statisticalMap.get(target.getId());
                }
                updateRzStatistical(target, dataList, statisticalList, list, dataInfoVo, enterpriseInfoMap);
            });
        }
        try {
            partitionSave(dataList);
            return true;
        } catch (Exception e) {
            log.error("人资大屏报表实际数据生成失败:{}", e.getMessage());
            return false;
        }
    }

    @Override
    public List<FaTargetRespVo> data(ReportReqVo t) {
        if (StringUtils.isEmpty(t.getTargetId())) {
            t.setTargetLevel("1");
        }
        //获取当前指标的年季月趋势数据
        if (null == t.getYear() || t.getYear() <= 0) {
            int year = LocalDate.now().getYear();
            t.setYear(year);
        }

        if (null == t.getStartYear() || null == t.getEndYear()) {
            t.setEndYear(t.getYear());
            t.setStartYear(t.getYear() - 5);
        }
        List<QfRzStatistical> list = this.baseMapper.getGroupData(t);
        List<FaTargetRespVo> resultList = Lists.newArrayList();
        //最终要展示的指标数据
        Map<String, List<QfRzStatistical>> taggetMap = list.stream().collect(Collectors.groupingBy(QfRzStatistical::getTargetCode));
        for (HrTargetTypeEnum state : HrTargetTypeEnum.values()) {
            FaTargetRespVo resultFa = new FaTargetRespVo();
            resultFa.setTargetId(state.getTargetId());
            resultFa.setTargetName(state.getTargetName());
            resultFa.setTargetNameEn(state.getTargetNameEn());
            resultFa.setTargetUnit(state.getTargetUnit());
            resultFa.setStaLat(state.getStaLat());
            resultFa.setType("1");
            resultFa.setSn(state.getType());
            List<String> stalat = Arrays.asList(state.getStaLat().split("、"));
            List<String> targetCodes = Arrays.asList(state.getTargetCodes().split("、"));
            List<QfRzStatistical> qfRzStatisticals = Lists.newArrayList();
            if (CollectionUtils.isEmpty(taggetMap)) {
                resultList.add(resultFa);
                continue;
            }
            for (String targetCode : targetCodes) {
                if (taggetMap.containsKey(targetCode)) {
                    qfRzStatisticals.addAll(taggetMap.get(targetCode));
                }
            }
            Map<Integer, List<QfRzStatistical>> yearMap = qfRzStatisticals.stream().collect(Collectors.groupingBy(QfRzStatistical::getYear));
            List<FaReportRespVo> reportRespVos = Lists.newArrayList();
            yearMap.forEach((year, v) -> {
                Map<String, QfRzStatistical> targetMap = yearMap.get(year).stream().collect(Collectors.toMap(item -> item.getTargetCode(), item -> item));
                FaReportRespVo faReportRespVo = new FaReportRespVo();
                faReportRespVo.setYear(year);
                JSONObject json = new JSONObject();
                Integer count = 0;
                for (String targetCode : targetCodes) {
                    QfRzStatistical rzStatistical = targetMap.get(targetCode);
                    if ("%".equals(rzStatistical.getTargetUnit())) {
                        if (null != rzStatistical.getCount() && null != rzStatistical.getActual()) {
                            BigDecimal actual = rzStatistical.getActual().divide(new BigDecimal(rzStatistical.getCount()), 2, BigDecimal.ROUND_HALF_UP);
                            rzStatistical.setActual(actual);
                        }

                    } else if ("万欧".equals(rzStatistical.getTargetUnit())) {
                        if (null != rzStatistical.getActual()) {
                            BigDecimal actual = rzStatistical.getActual().divide(new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP);
                            rzStatistical.setActual(actual);
                        }
                    }
                    json.put(stalat.get(count), rzStatistical.getActual());
                    count++;
                }
                faReportRespVo.setJson(json);
                reportRespVos.add(faReportRespVo);
            });
            resultFa.setResultData(reportRespVos);
            resultList.add(resultFa);
        }

        return resultList;
    }

    @Override
    public List<FaTargetRespVo> fromUnderData(ReportReqVo t) {
        Assert.hasText(t.getTargetId(), "请选择要统计的指标id");
        List<FaTargetRespVo> resultList = Lists.newArrayList();

        QfEnterpriseInfo group = enterpriseInfoManager.getGroup();
        if (StringUtil.isEmpty(t.getEnterpriseCode()) || group.getCode().equals(t.getEnterpriseCode())) {
            t.setEnterpriseCode(group.getCode());
            t.setType(2);
        } else {
            t.setType(1);
        }
        HrTargetTypeEnum state = HrTargetTypeEnum.findByTargetId(t.getTargetId());
        List<String> targetCodes = Arrays.asList(state.getTargetCodes().split("、"));
        QueryWrapper<SysSubjectTarget> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("code_", targetCodes);
        List<SysSubjectTarget> targetList = sysSubjectTargetManager.list(queryWrapper);

        //同比分析
        comparedAnalysis(t, resultList, targetCodes, targetList, "3");
        //环比分析
        sequentialAnalysis(t, resultList, targetCodes, targetList, "4");
        //当月分析
        monthAnalysis(t, resultList, state, targetCodes, "1");
        if (t.getType().equals(2)) {
            //生产企业分析
            productionEnterpriseAnalysis(t, resultList, state, targetCodes, "6");
            //非生产企业分析
//            nonProductionEnterpriseAnalysis(t, resultList, state, targetCodes, "7");
        }

        return resultList;
    }

    private void nonProductionEnterpriseAnalysis(ReportReqVo t, List<FaTargetRespVo> resultList, HrTargetTypeEnum state, List<String> targetCodes, String type) {
        DateReqVo dateReqVo = financialTimeUtils.processDateReqVo(t, type);
        financialTimeUtils.processDateQuery(t, dateReqVo);

        t.setEnterpriseType(null);
        List<QfRzStatistical> yearData = this.baseMapper.enterpriseAnalysis(t, targetCodes);
        FaTargetRespVo resultFa = getFaTargetRespVo(state, type);
        resultFa.setTargetName("非生产企业实际分析");
        if (CollectionUtils.isEmpty(yearData)) {
            resultList.add(resultFa);
            return;
        }
        //最终要展示的指标数据
        Map<String, List<QfRzStatistical>> taggetMap = yearData.stream().collect(Collectors.groupingBy(QfRzStatistical::getTargetCode));

        List<QfRzStatistical> qfRzStatisticals = Lists.newArrayList();

        for (String targetCode : targetCodes) {
            qfRzStatisticals.addAll(taggetMap.get(targetCode));
        }
        Map<String, List<QfRzStatistical>> yearMap = qfRzStatisticals.stream().collect(Collectors.groupingBy(QfRzStatistical::getEnterpriseCode));
        List<FaReportRespVo> reportRespVos = Lists.newArrayList();
        yearMap.forEach((enterpriseCode, v) -> {
            Map<String, QfRzStatistical> targetMap = v.stream().collect(Collectors.toMap(item -> item.getTargetCode(), item -> item));
            FaReportRespVo faReportRespVo = new FaReportRespVo();
            faReportRespVo.setEnterpriseCode(enterpriseCode);
            JSONObject json = new JSONObject();
            for (String targetCode : targetCodes) {
                if (!taggetMap.containsKey(targetCode)) {
                    continue;
                }
                QfRzStatistical rzStatistical = targetMap.get(targetCode);
                json.put(rzStatistical.getTargetName(), rzStatistical.getActual());
            }
            faReportRespVo.setJson(json);
            reportRespVos.add(faReportRespVo);
        });
        resultList.add(resultFa);
    }

    private void productionEnterpriseAnalysis(ReportReqVo t, List<FaTargetRespVo> resultList, HrTargetTypeEnum state, List<String> targetCodes, String type) {
        DateReqVo dateReqVo = financialTimeUtils.processDateReqVo(t, type);
        financialTimeUtils.processDateQuery(t, dateReqVo);
        t.setEnterpriseType(1);
        List<QfRzStatistical> yearData = this.baseMapper.enterpriseAnalysis(t, targetCodes);
        FaTargetRespVo resultFa = getFaTargetRespVo(state, type);
        resultFa.setTargetName("生产企业实际分析");
        if (CollectionUtils.isEmpty(yearData)) {
            resultList.add(resultFa);
            return;
        }
        if("万欧".equals(state.getTargetUnit())) {
            yearData.forEach(detail -> {
                BigDecimal actual = detail.getActual().divide(new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP);
                detail.setActual(actual);
            });
        }
        //最终要展示的指标数据
        Map<String, List<QfRzStatistical>> taggetMap = yearData.stream().collect(Collectors.groupingBy(QfRzStatistical::getTargetCode));

        List<QfRzStatistical> qfRzStatisticals = Lists.newArrayList();

        for (String targetCode : targetCodes) {
            qfRzStatisticals.addAll(taggetMap.get(targetCode));
        }
        Map<String, List<QfRzStatistical>> yearMap = qfRzStatisticals.stream().collect(Collectors.groupingBy(QfRzStatistical::getEnterpriseCode));
        List<FaReportRespVo> reportRespVos = Lists.newArrayList();
        yearMap.forEach((enterpriseCode, v) -> {
            Map<String, QfRzStatistical> targetMap = v.stream().collect(Collectors.toMap(item -> item.getTargetCode(), item -> item));
            FaReportRespVo faReportRespVo = new FaReportRespVo();
            faReportRespVo.setEnterpriseCode(enterpriseCode);
            JSONObject json = new JSONObject();
            for (String targetCode : targetCodes) {
                if (!taggetMap.containsKey(targetCode)) {
                    continue;
                }
                QfRzStatistical rzStatistical = targetMap.get(targetCode);
                if ("FE150、FE151、FE153、FE154、FE155、FR156、FE157".contains(targetCode)) {
                    rzStatistical.setTargetName(rzStatistical.getTargetName().substring(0, 4));
                }
                json.put(rzStatistical.getTargetName(), rzStatistical.getActual());
            }
            faReportRespVo.setJson(json);
            reportRespVos.add(faReportRespVo);
        });
        resultFa.setResultData(reportRespVos);
        resultList.add(resultFa);
    }

    private void sequentialAnalysis(ReportReqVo t, List<FaTargetRespVo> resultList, List<String> targetCodes, List<SysSubjectTarget> targetList, String type) {
        DateReqVo dateReqVo = financialTimeUtils.processDateReqVo(t, type);
        financialTimeUtils.processDateQuery(t, dateReqVo);
        List<FaReportRespVo> list = this.baseMapper.sequentialAnalysis(t, targetCodes);
        if (CollectionUtils.isEmpty(list)) {
            return;
        }

        Map<String, SysSubjectTarget> targetMap = targetList.stream().collect(Collectors.toMap(item -> item.getId(), item -> item));
        Map<String, List<FaReportRespVo>> targetDataMap = list.stream().collect(Collectors.groupingBy(FaReportRespVo::getTargetId));
        targetDataMap.forEach((targetId, v) -> {
            if (!targetMap.containsKey(targetId)) {
                return;
            }
            SysSubjectTarget target = targetMap.get(targetId);
            List<FaReportRespVo> reportRespVos = Lists.newArrayList();
            if (!CollectionUtils.isEmpty(list)) {

                Map<Integer, FaReportRespVo> respVoMap = v.stream().collect(Collectors.toMap(item -> item.getMonth(), item -> item));
                for (int i = 1; i < t.getEndMonth(); i++) {
                    if (i == 1) {
                        continue;
                    }
                    FaReportRespVo faReportRespVo = new FaReportRespVo();
                    BigDecimal currentMonthActual = BigDecimal.ZERO;
                    BigDecimal lastMonthActual = BigDecimal.ZERO;
                    if (respVoMap.containsKey(i) && null != respVoMap.get(i).getActual()) {
                        currentMonthActual = respVoMap.get(i).getActual();
                    }
                    if (respVoMap.containsKey(i - 1) && null != respVoMap.get(i - 1).getActual()) {
                        lastMonthActual = respVoMap.get(i - 1).getActual();
                    }
                    faReportRespVo.setMonth(i);
                    faReportRespVo.setYear(t.getYear());
                    faReportRespVo.setTargetId(t.getTargetId());
                    faReportRespVo.setActual(currentMonthActual.subtract(lastMonthActual));
                    if (lastMonthActual.doubleValue() != 0) {
                        BigDecimal growthRate = currentMonthActual.subtract(lastMonthActual).divide(lastMonthActual, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));
                        faReportRespVo.setGrowthRate(growthRate);
                    } else {
                        faReportRespVo.setGrowthRate(BigDecimal.ZERO);
                    }

                    reportRespVos.add(faReportRespVo);
                }
            }
            FaTargetTypeEnum targetTypeEnum = FaTargetTypeEnum.getTarget(type);
            FaTargetRespVo resultFa = financialTimeUtils.getCurrentFaTargetRespVo(targetTypeEnum, target, type, reportRespVos);
            resultFa.setResultData(reportRespVos);
            resultFa.setTargetName(target.getName() + resultFa.getTargetName());
            resultFa.setTargetNameEn(target.getTargetNameEn() + resultFa.getTargetNameEn());
            resultFa.setStaLat("实际数");
            resultList.add(resultFa);

        });
    }

    private void comparedAnalysis(ReportReqVo t, List<FaTargetRespVo> resultList, List<String> targetCodes, List<SysSubjectTarget> targetList, String type) {
        DateReqVo dateReqVo = financialTimeUtils.processDateReqVo(t, type);
        financialTimeUtils.processDateQuery(t, dateReqVo);
        List<FaReportRespVo> list = this.baseMapper.comparedAnalysis(t, targetCodes);
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        Map<String, SysSubjectTarget> targetMap = targetList.stream().collect(Collectors.toMap(item -> item.getId(), item -> item));
        Map<String, List<FaReportRespVo>> targetDataMap = list.stream().collect(Collectors.groupingBy(FaReportRespVo::getTargetId));
        JSONObject currentYearBeforeMonth = new JSONObject(true);
        JSONObject beforeYearBeforeMonth = new JSONObject(true);
        targetDataMap.forEach((targetId, v) -> {
            if (!targetMap.containsKey(targetId)) {
                return;
            }
            SysSubjectTarget target = targetMap.get(targetId);
            FaTargetTypeEnum targetTypeEnum = FaTargetTypeEnum.getTarget(type);
            FaTargetRespVo resultFa = financialTimeUtils.getCurrentFaTargetRespVo(targetTypeEnum, target, type, list);
            Map<Integer, List<FaReportRespVo>> monthMap = v.stream().collect(Collectors.groupingBy(FaReportRespVo::getMonth));
            List<FaReportRespVo> resultData = Lists.newArrayList();
            monthMap.forEach((month, data) -> {
                if (data.size() <= 1) {
                    return;
                }
                BigDecimal thisYearActual = data.get(data.size() - 1).getActual();
                BigDecimal lastYearActual = data.get(0).getActual();
                currentYearBeforeMonth.put(target.getCode() + month, thisYearActual);
                beforeYearBeforeMonth.put(target.getCode() + month, lastYearActual);
                if ("FE150、FE151".contains(target.getCode())) {
                    if (currentYearBeforeMonth.containsKey(target.getCode() + (month - 1))) {
                        thisYearActual = thisYearActual.subtract(currentYearBeforeMonth.getBigDecimal(target.getCode() + (month - 1)));
                        data.get(data.size() - 1).setActual(thisYearActual);
                    }
                    if (currentYearBeforeMonth.containsKey(target.getCode() + (month - 1))) {
                        lastYearActual = lastYearActual.subtract(beforeYearBeforeMonth.getBigDecimal(target.getCode() + (month - 1)));
                        data.get(0).setActual(lastYearActual);
                    }
                }

                BigDecimal growthRate = null;
                if (null == lastYearActual || lastYearActual.doubleValue() == 0) {
                    growthRate = BigDecimal.ZERO;
                } else {
                    growthRate = thisYearActual.subtract(lastYearActual).divide(lastYearActual, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));
                }
                for (FaReportRespVo resp : data) {
                    resp.setGrowthRate(growthRate);
                    resultData.add(resp);
                }
            });
            resultData.sort(Comparator.comparing(FaReportRespVo::getMonth));
            resultFa.setResultData(resultData);
            resultFa.setTargetName(target.getName() + resultFa.getTargetName());
            resultFa.setTargetNameEn(target.getTargetNameEn() + resultFa.getTargetNameEn());
            resultFa.setStaLat("实际数");
            resultList.add(resultFa);
        });

    }

    private void monthAnalysis(ReportReqVo t, List<FaTargetRespVo> resultList, HrTargetTypeEnum state, List<String> targetCodes, String type) {
        DateReqVo dateReqVo = financialTimeUtils.processDateReqVo(t, type);
        financialTimeUtils.processDateQuery(t, dateReqVo);

        List<QfRzStatistical> yearData = this.baseMapper.yearData(t, targetCodes);
        if (CollectionUtils.isEmpty(yearData)) {
            return;
        }
        if("万欧".equals(state.getTargetUnit())) {
            yearData.forEach(detail -> {
                BigDecimal actual = detail.getActual().divide(new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP);
                detail.setActual(actual);
            });
        }

        //最终要展示的指标数据
        Map<String, List<QfRzStatistical>> taggetMap = yearData.stream().collect(Collectors.groupingBy(QfRzStatistical::getTargetCode));
        FaTargetRespVo resultFa = getFaTargetRespVo(state, type);
        List<QfRzStatistical> qfRzStatisticals = Lists.newArrayList();

        for (String targetCode : targetCodes) {
            qfRzStatisticals.addAll(taggetMap.get(targetCode));
        }
        Map<Integer, List<QfRzStatistical>> yearMap = qfRzStatisticals.stream().collect(Collectors.groupingBy(QfRzStatistical::getMonth));
        List<FaReportRespVo> reportRespVos = Lists.newArrayList();
        JSONObject beforeJson = new JSONObject(true);
        yearMap.forEach((month, v) -> {
            Map<String, QfRzStatistical> targetMap = v.stream().collect(Collectors.toMap(item -> item.getTargetCode(), item -> item));
            FaReportRespVo faReportRespVo = new FaReportRespVo();
            faReportRespVo.setMonth(month);
            JSONObject json = new JSONObject(true);

            for (String targetCode : targetCodes) {
                if (!taggetMap.containsKey(targetCode)) {
                    continue;
                }
                QfRzStatistical rzStatistical = targetMap.get(targetCode);
                if ("FE150、FE151、FE153、FE154、FE155、FE156、FE157".contains(targetCode)) {
                    rzStatistical.setTargetName(rzStatistical.getTargetName().substring(0, 4));
                }
                beforeJson.put(targetCode + month, rzStatistical.getActual());
                faReportRespVo.setYear(rzStatistical.getYear());
                json.put(rzStatistical.getTargetName(), rzStatistical.getActual());
                if ("FE150、FE151、FE152、FE153、FE155、FE157".contains(targetCode)) {
                    if (beforeJson.containsKey(targetCode + (month - 1))) {
                        json.put(rzStatistical.getTargetName(), rzStatistical.getActual().subtract(beforeJson.getBigDecimal(targetCode + (month - 1))));
                    }
                }
            }
            faReportRespVo.setJson(json);
            reportRespVos.add(faReportRespVo);
        });
        resultFa.setResultData(reportRespVos);
        resultFa.setTargetName("当月实际");
        resultList.add(resultFa);
    }


    private FaTargetRespVo getFaTargetRespVo(HrTargetTypeEnum state, String type) {
        FaTargetTypeEnum targetTypeEnum = FaTargetTypeEnum.getTarget(type);
        FaTargetRespVo resultFa = new FaTargetRespVo();
        resultFa.setTargetName(targetTypeEnum.getTargetName());
        resultFa.setTargetNameEn(targetTypeEnum.getTargetNameEn());
        resultFa.setTargetId(state.getTargetId());
        resultFa.setTargetUnit(state.getTargetUnit());
        resultFa.setStaLat(state.getStaLat());
        resultFa.setType(type);
        resultFa.setSn(state.getType());
        if (!StringUtils.isEmpty(state.getTargetUnit()) && "欧".equals(state.getTargetUnit())) {
            resultFa.setTargetUnit("万欧");
        }
        return resultFa;
    }

    @Override
    public List<FaTargetRespVo> enterpriseData(ReportReqVo t) {
        Assert.hasText(t.getTargetId(), "请选择要统计的指标id");
        List<FaTargetRespVo> resultList = Lists.newArrayList();
        int year = LocalDate.now().getYear();
        t.setYear(year);
        HrTargetTypeEnum state = HrTargetTypeEnum.findByTargetId(t.getTargetId());
        FaTargetRespVo resultFa = new FaTargetRespVo();
        resultFa.setTargetId(state.getTargetId());
        resultFa.setTargetName(state.getTargetName());
        resultFa.setTargetNameEn(state.getTargetNameEn());
        resultFa.setTargetUnit(state.getTargetUnit());
        if (!StringUtils.isEmpty(state.getTargetUnit()) && "欧".equals(state.getTargetUnit())) {
            resultFa.setTargetUnit("万欧");
        }
        resultFa.setStaLat(state.getStaLat());
        resultFa.setType("5");
        resultFa.setSn(state.getType());
        List<String> stalat = Arrays.asList(state.getStaLat().split("、"));
        List<String> targetCodes = Arrays.asList(state.getTargetCodes().split("、"));
        List<QfRzStatistical> enterpriseData = this.baseMapper.enterpriseData(t, targetCodes);

        //最终要展示的指标数据
        Map<String, List<QfRzStatistical>> taggetMap = enterpriseData.stream().collect(Collectors.groupingBy(QfRzStatistical::getTargetCode));
        List<QfRzStatistical> qfRzStatisticals = Lists.newArrayList();

        for (String targetCode : targetCodes) {
            qfRzStatisticals.addAll(taggetMap.get(targetCode));
        }
        Map<String, List<QfRzStatistical>> enterpriseCodeMap = qfRzStatisticals.stream().collect(Collectors.groupingBy(QfRzStatistical::getEnterpriseCode));
        List<FaReportRespVo> reportRespVos = Lists.newArrayList();
        enterpriseCodeMap.forEach((enterpriseCode, v) -> {
            Map<String, QfRzStatistical> targetMap = enterpriseCodeMap.get(enterpriseCode).stream().collect(Collectors.toMap(item -> item.getTargetCode(), item -> item));
            FaReportRespVo faReportRespVo = new FaReportRespVo();
            faReportRespVo.setEnterpriseCode(enterpriseCode);
            JSONObject json = new JSONObject();
            Integer count = 0;
            for (String targetCode : targetCodes) {
                QfRzStatistical rzStatistical = targetMap.get(targetCode);
                if ("%".equals(rzStatistical.getTargetUnit())) {
                    if (null != rzStatistical.getCount() && null != rzStatistical.getActual()) {
                        BigDecimal actual = rzStatistical.getActual().divide(new BigDecimal(rzStatistical.getCount()), 2, BigDecimal.ROUND_HALF_UP);
                        rzStatistical.setActual(actual);
                    }

                } else {
                    if (null != rzStatistical.getCount() && null != rzStatistical.getActual()) {
                        BigDecimal actual = rzStatistical.getActual().divide(new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP);
                        rzStatistical.setActual(actual);
                    }
                }
                json.put(stalat.get(count), rzStatistical.getActual());
                count++;
            }
            faReportRespVo.setJson(json);
            reportRespVos.add(faReportRespVo);
        });
        resultFa.setResultData(reportRespVos);
        resultList.add(resultFa);
        return resultList;
    }


    private void updateRzStatistical(SysSubjectTarget target,
                                     List<QfRzStatistical> dataList,
                                     List<QfRzStatistical> statisticalList,
                                     List<ReportVo> list, DataInfoVo dataInfoVo, Map<String, QfEnterpriseInfo> enterpriseInfoMap) {

        if (CollectionUtils.isEmpty(statisticalList)) {
            return;
        }
        //将已经产生的大屏统计数据根据企业编号分组
        Map<String, List<QfRzStatistical>> statisticalMap = statisticalList.stream().collect(Collectors.groupingBy(QfRzStatistical::getEnterpriseCode));
        String targetCalculation = target.getTargetCalculation();
        List<String> expressionKey = CommonUtil.getExpressionKey(targetCalculation);

        Map<String, List<ReportVo>> enterpriseReportMap = list.stream().collect(Collectors.groupingBy(ReportVo::getEnterpriseCode));
        enterpriseReportMap.forEach((enterpriseCode, financialVoList) -> {
            if (!enterpriseInfoMap.containsKey(enterpriseCode)) {
                return;
            }
            //获取对应企业信息
            QfEnterpriseInfo qfEnterpriseInfo = enterpriseInfoMap.get(enterpriseCode);
            //获取当前企业相关的大屏统计数据
            List<ReportVo> reportVos = enterpriseReportMap.get(enterpriseCode);
            if (statisticalMap.containsKey(enterpriseCode)) {
                List<QfRzStatistical> statisticals = statisticalMap.get(enterpriseCode);
                //将已产生的企业大屏数据根据指标进行map转换，获取对应企业当前指标的统计数据
                Map<String, QfRzStatistical> faMap = statisticals.stream().collect(Collectors.toMap(item -> item.getTargetId(), item -> item));
                QfRzStatistical rzStatistical = null;
                //判断当前指标是否已经产生数据，没有则新增，有则进行修改
                if (faMap.containsKey(target.getId())) {
                    rzStatistical = faMap.get(target.getId());
                    rzStatistical.setTempCalculation(targetCalculation);
                } else {
                    rzStatistical = new QfRzStatistical();
                    rzStatistical.setTempCalculation(targetCalculation);
                    rzStatistical.setEnterpriseCode(enterpriseCode);
                    createInfo(target, dataInfoVo, rzStatistical);
                }
                if (!StringUtil.isNotEmpty(target.getAnalyseType()) || !AnalyseTypeEnum.getAreaType().contains(target.getAnalyseType())) {
                    if (!StringUtil.isEmpty(qfEnterpriseInfo.getContinent())) {
                        rzStatistical.setEnterpriseArea(Integer.parseInt(qfEnterpriseInfo.getContinent()));
                    }
                    rzStatistical.setEnterpriseType(qfEnterpriseInfo.getBusinessType());
                    dataList.add(rzStatistical);
                }

                calculateData(targetCalculation, expressionKey, reportVos, rzStatistical);
                rzStatistical.setTempCalculation(targetCalculation);
                dataList.add(rzStatistical);

            }
        });

    }

    private void saveRzStatistical(SysSubjectTarget target,
                                   List<QfRzStatistical> dataList,
                                   List<ReportVo> list,
                                   DataInfoVo dataInfoVo,
                                   Map<String, QfEnterpriseInfo> enterpriseInfoMap) {

        Map<String, List<ReportVo>> enterpriseMap = list.stream().collect(Collectors.groupingBy(ReportVo::getEnterpriseCode));

        String targetCalculation = target.getTargetCalculation();
        List<String> expressionKey = CommonUtil.getExpressionKey(targetCalculation);
        enterpriseMap.forEach((enterpriseCode, rzVoList) -> {
            if (!enterpriseInfoMap.containsKey(enterpriseCode)) {
                return;
            }
            QfEnterpriseInfo qfEnterpriseInfo = enterpriseInfoMap.get(enterpriseCode);
            QfRzStatistical rzStatistical = new QfRzStatistical();
            rzStatistical.setTempCalculation(targetCalculation);
            createInfo(target, dataInfoVo, rzStatistical);
            calculateData(targetCalculation, expressionKey, rzVoList, rzStatistical);

            if (!StringUtil.isNotEmpty(target.getAnalyseType()) || !AnalyseTypeEnum.getAreaType().contains(target.getAnalyseType())) {
                if (!StringUtil.isEmpty(qfEnterpriseInfo.getContinent())) {
                    rzStatistical.setEnterpriseArea(Integer.parseInt(qfEnterpriseInfo.getContinent()));
                }
                rzStatistical.setEnterpriseType(qfEnterpriseInfo.getBusinessType());
                rzStatistical.setEnterpriseCode(enterpriseCode);
                dataList.add(rzStatistical);
            }

        });

    }

    /**
     * 根据公式计算大屏企业指标数据
     *
     * @param targetCalculation
     * @param expressionKey
     * @param financialVoList
     * @param rzStatistical
     */
    private void calculateData(String targetCalculation,
                               List<String> expressionKey,
                               List<ReportVo> financialVoList,
                               QfRzStatistical rzStatistical) {
        Integer dataType = 1;
        String targetCalculationJson = rzStatistical.getTargetCalculation();
        Map<Integer, Map<String, BigDecimal>> map = JSONObject.parseObject(targetCalculationJson, Map.class);
        if (CollectionUtils.isEmpty(map)) {
            map = Maps.newHashMap();
        }
        Map<String, BigDecimal> targetCalculationMap = Maps.newHashMap();
        Map<Integer, Map<String, BigDecimal>> finalMap = map;
        expressionKey.forEach(key -> {
            if (StringUtils.isEmpty(key)) {
                return;
            }
            key = "U" + key;
            for (ReportVo financialVo : financialVoList) {
                if (StringUtils.isEmpty(financialVo.getSubjectCode()) || !financialVo.getSubjectCode().equals(key.substring(1))) {
                    continue;
                }

                if (dataType == 1 && null == financialVo.getActualYtd()) {
                    financialVo.setActual(BigDecimal.ZERO);
                }

                if (dataType == 2 && null == financialVo.getBudget()) {
                    financialVo.setBudget(BigDecimal.ZERO);
                }

                if (CollectionUtils.isEmpty(finalMap)) {
                    targetCalculationMap.put(key, dataType == 1 ? financialVo.getActualYtd() : financialVo.getBudget());
                    finalMap.put(dataType, targetCalculationMap);
                } else {
                    Map<String, BigDecimal> stringBigDecimalMap = finalMap.get(dataType);
                    if (!CollectionUtils.isEmpty(stringBigDecimalMap)) {
                        //将之前已经计算的用新数据替换
                        for (Map.Entry<String, BigDecimal> entry : stringBigDecimalMap.entrySet()
                        ) {
                            if (key.equals(entry.getKey())) {
                                targetCalculationMap.put(entry.getKey(), dataType == 1 ? financialVo.getActualYtd() : financialVo.getBudget());
                            }
                        }
                        //在替换掉之前已计算公式后，如果当前数据之前未加入计算公式，则继续新增
                        if (!targetCalculationMap.containsKey(key)) {
                            targetCalculationMap.put(key, dataType == 1 ? financialVo.getActualYtd() : financialVo.getBudget());
                        }
                        finalMap.put(dataType, targetCalculationMap);
                    } else {
                        targetCalculationMap.put(key, dataType == 1 ? financialVo.getActualYtd() : financialVo.getBudget());
                        finalMap.put(dataType, targetCalculationMap);
                    }
                }

                if (expressionKey.size() == targetCalculationMap.size()) {
                    continue;
                }
            }
        });
        //补0操作
        for (String key : expressionKey) {
            key = "U" + key;
            if (!targetCalculationMap.containsKey(key)) {
                targetCalculationMap.put(key, BigDecimal.ZERO);
            }
        }
        targetCalculation = CommonUtil.replaceExpression(expressionKey, targetCalculation);
        log.info("expressionKey:{},targetCalculation:{},targetCalculationMap:{}", expressionKey, targetCalculation, targetCalculationMap);
        rzStatistical.setTargetCalculation(JSON.toJSONString(finalMap));
        if (!StringUtil.isNotEmpty(targetCalculation)) {
            return;
        }
        //1.需要单独公式计算的不在此次计算范围内 2.计算公式数量=匹配上的科目数量
        if (expressionKey.size() == targetCalculationMap.size()) {
            int margin = 4;
            if ("人".equals(rzStatistical.getTargetUnit())) {
                margin = 0;
            }

            BigDecimal bigDecimal = CommonUtil.convertToCode(targetCalculation, targetCalculationMap, margin);
            if (StringUtil.isNotEmpty(rzStatistical.getTargetCalculation()) && "%".equals(rzStatistical.getTargetUnit())) {
                //如果不是增长率且单位是%的 需要*100
                bigDecimal = bigDecimal.multiply(new BigDecimal(100));
            }
            rzStatistical.setActual(bigDecimal);
        }
    }

    private void createInfo(SysSubjectTarget target, DataInfoVo dataInfoVo, QfRzStatistical rzStatistical) {
        rzStatistical.setTargetId(target.getId());
        rzStatistical.setTargetLevel(target.getTargetLevel());
        rzStatistical.setTargetName(target.getName());
        rzStatistical.setTargetNameEn(target.getTargetNameEn());
        rzStatistical.setTargetUnit(target.getUnit());
        rzStatistical.setType(target.getType());
        rzStatistical.setStaLat(target.getStaLat());
        rzStatistical.setLargerType(target.getLargerType());
        rzStatistical.setParentTargetId(target.getParentId());
        rzStatistical.setYear(dataInfoVo.getYear());
        rzStatistical.setQuarter(dataInfoVo.getQuarter());
        rzStatistical.setMonth(dataInfoVo.getMonth());
    }

    private void partitionSave(List<QfRzStatistical> detailList) throws InterruptedException {
        List<List<QfRzStatistical>> partition = BeanUtils.partition(detailList, detailList.size() / 10);
        // 创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(partition.size());
        // 声明线程计数器 记录单个任务的执行次数
        CountDownLatch countDownLatch = new CountDownLatch(partition.size());
        // 遍历处理拆分的list数据
        for (int i = 0; i < partition.size(); i++) {
            int finalI = i;
            executorService.execute(() -> {
                // 业务处理部分
                List<QfRzStatistical> importParamDTOList = partition.get(finalI);
                this.saveOrUpdateBatch(importParamDTOList);
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        //关闭线程池
        executorService.shutdown();
    }

}
