package com.xiaoniu.subsystem.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xiaoniu.common.core.utils.DateUtils;
import com.xiaoniu.common.core.utils.StringUtils;
import com.xiaoniu.common.core.vo.AnalysisLineVO;
import com.xiaoniu.common.core.vo.LabelAndValueNameVO;
import com.xiaoniu.common.core.vo.LabelAndValueVO;
import com.xiaoniu.common.security.utils.SecurityUtils;
import com.xiaoniu.subsystem.business.domain.Expense;
import com.xiaoniu.subsystem.business.domain.Flight;
import com.xiaoniu.subsystem.business.domain.Project;
import com.xiaoniu.subsystem.business.domain.ProjectPersonnelInfo;
import com.xiaoniu.subsystem.business.domain.dto.ExpenseStatisticsDTO;
import com.xiaoniu.subsystem.business.domain.vo.*;
import com.xiaoniu.subsystem.business.mapper.*;
import com.xiaoniu.subsystem.business.service.IStatisticalAnalysisService;
import com.xiaoniu.subsystem.system.domain.Unit;
import com.xiaoniu.subsystem.system.mapper.UnitMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Year;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.xiaoniu.common.security.utils.SecurityUtils.getUnitId;

/**
 * @Author haoxuyang
 * @Date 2024/11/29 14:27
 */
@Service
public class StatisticalAnalysisServiceImpl implements IStatisticalAnalysisService {
    @Resource
    private ProjectPersonnelInfoMapper projectPersonnelInfoMapper;
    @Resource
    private ProjectMapper projectMapper;
    @Resource
    private UnitMapper unitMapper;
    @Resource
    private ExpenseMapper expenseMapper;
    @Resource
    private FlightMapper flightMapper;
    @Resource
    private DemandMapper demandMapper;

    @Override
    public AnalysisLineVO excellentStudent() {
        AnalysisLineVO analysisLineVO = new AnalysisLineVO();
        List<AnalysisLineVO.DataList> dataList = new ArrayList<>();
        AnalysisLineVO.DataList list = new AnalysisLineVO.DataList();
        list.setName("历年优秀学员统计");
        list.setType("column");
        list.setYAxisData(new ArrayList<>());
        List<String> xAxisData = new ArrayList<>();
        // 获取当前年份
        List<String> yearList = DateUtils.getYearCollectionExample(6);
        Long unitId = getUnitId();
        if (StringUtils.isNull(unitId)) {
            return analysisLineVO;
        }
        // 获取子级部门id
        List<Long> unitIdList = unitMapper.juniorUnit(unitId);

        // 计算历年优秀学院数量
        List<LabelAndValueVO> excellentStudentList = projectPersonnelInfoMapper.getExcellentStudent(yearList, unitIdList);
        Map<String, String> map = new HashMap<>();
        if (!CollectionUtils.isEmpty(excellentStudentList)) {
            map = excellentStudentList.stream().collect(Collectors.toMap(LabelAndValueVO::getValue, LabelAndValueVO::getLabel));
        }
        for (String year : yearList) {
            xAxisData.add(year);
            if (!CollectionUtils.isEmpty(map)) {
                list.getYAxisData().add(StringUtils.isNotEmpty(map.get(year)) ? map.get(year) : "0");
            } else {
                list.getYAxisData().add("0");
            }
        }
        dataList.add(list);
        analysisLineVO.setXAxisData(xAxisData);
        analysisLineVO.setDataList(dataList);
        return analysisLineVO;
    }

    @Override
    public NumberParticipantsVO numberParticipants() {
        NumberParticipantsVO numberParticipantsVO = new NumberParticipantsVO();
        Long unitId = getUnitId();
        if (StringUtils.isNull(unitId)) {
            return numberParticipantsVO;
        }
        // 获取子级部门id
        List<Long> unitIdList = unitMapper.juniorUnit(unitId);
        unitIdList.remove(unitId);
        // 获取当前年份
        List<String> yearList = DateUtils.getYearCollectionExample(6);
        // 获取计划参训人数
        Integer planParticipate = projectMapper.getPlanParticipateNum(unitIdList, yearList, null);
        numberParticipantsVO.setPlanParticipate(planParticipate);
        // 获取实际参训人数
        Integer actualParticipate = projectPersonnelInfoMapper.getActualParticipateNum(unitIdList, yearList, null);
        numberParticipantsVO.setActualParticipate(actualParticipate);

        AnalysisLineVO analysisLineVO = new AnalysisLineVO();
        List<AnalysisLineVO.DataList> dataList = new ArrayList<>();
        List<String> xAxisData = new ArrayList<>();


        List<ParticipantsVO> participantsList = projectPersonnelInfoMapper.getNumberParticipants(yearList, unitIdList);
        if (CollectionUtils.isEmpty(participantsList)) {
            return numberParticipantsVO;
        }

        Map<Long, List<ParticipantsVO>> map = participantsList.stream().collect(Collectors.groupingBy(ParticipantsVO::getSendingUnitId));
        for (Map.Entry<Long, List<ParticipantsVO>> entry : map.entrySet()) {
            List<ParticipantsVO> sendingUnitList = entry.getValue();
            AnalysisLineVO.DataList list = new AnalysisLineVO.DataList();
            list.setName(StringUtils.isNotNull(sendingUnitList.get(0).getSendingUnitName()) ? sendingUnitList.get(0).getSendingUnitName() : "");
            list.setType("column");
            list.setYAxisData(new ArrayList<>());
            Map<String, List<ParticipantsVO>> listMap = sendingUnitList.stream().collect(Collectors.groupingBy(ParticipantsVO::getYear));
            for (String year : yearList) {
                xAxisData.add(year);
                List<ParticipantsVO> participantsVOList = listMap.get(year);
                if (!CollectionUtils.isEmpty(participantsVOList)) {
                    list.getYAxisData().add(participantsVOList.stream().map(l ->
                                    BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getNum()) ?
                                            "0" : l.getNum())))
                            .reduce(BigDecimal.ZERO, BigDecimal::add).stripTrailingZeros().toPlainString());
                } else {
                    list.getYAxisData().add("0");
                }
            }
            dataList.add(list);
        }
        analysisLineVO.setDataList(dataList);
        analysisLineVO.setXAxisData(xAxisData.stream().distinct().collect(Collectors.toList()));
        numberParticipantsVO.setAnalysisLineVO(analysisLineVO);
        return numberParticipantsVO;
    }

    @Override
    public AnalysisLineVO overYearsParticipants() {
        AnalysisLineVO analysisLineVO = new AnalysisLineVO();
        List<AnalysisLineVO.DataList> dataList = new ArrayList<>();

        Long unitId = getUnitId();
        if (StringUtils.isNull(unitId)) {
            return analysisLineVO;
        }
        // 获取子级部门id
        List<Long> unitIdList = unitMapper.juniorUnit(unitId);
        // 获取当前年份
        List<String> yearList = DateUtils.getYearCollectionExample(6);
        // 获取实际参训人员
        List<LabelAndValueVO> projectPersonnelList = projectPersonnelInfoMapper.overYearsParticipants(unitIdList, yearList);
        Map<String, String> projectPersonnelMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(projectPersonnelList)) {
            projectPersonnelMap = projectPersonnelList.stream().collect(Collectors.toMap(LabelAndValueVO::getValue, LabelAndValueVO::getLabel));
        }
        // 获取计划参训人员
        List<LabelAndValueVO> projectList = projectMapper.overYearsParticipants(unitIdList, yearList);
        Map<String, String> projectMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(projectList)) {
            projectMap = projectList.stream().collect(Collectors.toMap(LabelAndValueVO::getValue, LabelAndValueVO::getLabel));
        }
        AnalysisLineVO.DataList list1 = new AnalysisLineVO.DataList();
        list1.setName("实际");
        list1.setType("line");
        list1.setYAxisData(new ArrayList<>());
        AnalysisLineVO.DataList list2 = new AnalysisLineVO.DataList();
        list2.setName("计划");
        list2.setType("line");
        list2.setYAxisData(new ArrayList<>());
        List<String> xAxisData = new ArrayList<>();

        for (String year : yearList) {
            xAxisData.add(year);
            if (!CollectionUtils.isEmpty(projectPersonnelMap)) {
                list1.getYAxisData().add(StringUtils.isNotEmpty(projectPersonnelMap.get(year)) ? projectPersonnelMap.get(year) : "0");
            } else {
                list1.getYAxisData().add("0");
            }
            if (!CollectionUtils.isEmpty(projectMap)) {
                list2.getYAxisData().add(StringUtils.isNotEmpty(projectMap.get(year)) ? projectMap.get(year) : "0");
            } else {
                list2.getYAxisData().add("0");
            }
        }
        dataList.add(list1);
        dataList.add(list2);
        analysisLineVO.setXAxisData(xAxisData);
        analysisLineVO.setDataList(dataList);
        return analysisLineVO;
    }

    @Override
    public List<LabelAndValueVO> trainingType() {
        Long unitId = getUnitId();
        if (StringUtils.isNull(unitId)) {
            return new ArrayList<>();
        }
        // 获取子级部门id
        List<Long> unitIdList = unitMapper.juniorUnit(unitId);
        return projectPersonnelInfoMapper.trainingType(unitIdList);
    }

    @Override
    public AnalysisLineVO comparisonGrades() {
        AnalysisLineVO analysisLineVO = new AnalysisLineVO();
        List<AnalysisLineVO.DataList> dataList = new ArrayList<>();
        AnalysisLineVO.DataList list1 = new AnalysisLineVO.DataList();
        list1.setName("入学摸底考试成绩");
        list1.setType("line");
        list1.setYAxisData(new ArrayList<>());
        AnalysisLineVO.DataList list2 = new AnalysisLineVO.DataList();
        list2.setName("结业考核成绩");
        list2.setType("line");
        list2.setYAxisData(new ArrayList<>());
        List<String> xAxisData = new ArrayList<>();
        // 获取当前年份
        List<String> yearList = DateUtils.getYearCollectionExample(6);
        Long unitId = getUnitId();
        if (StringUtils.isNull(unitId)) {
            return analysisLineVO;
        }
        // 获取子级部门id
        List<Long> unitIdList = unitMapper.juniorUnit(unitId);
//        List<Long> unitIdList= Arrays.asList(1L,2L,3L);

        List<ComparisonGradesVO> comparisonGradesList = projectPersonnelInfoMapper.comparisonGrades(unitIdList);
        List<ComparisonGradesVO> placementTest = comparisonGradesList.stream().filter(o -> o.getType().equals("placement_test")).toList();
        List<ComparisonGradesVO> finalTest = comparisonGradesList.stream().filter(o -> o.getType().equals("final_test")).toList();
        Map<String, BigDecimal> placementMap = new HashMap<>();
        Map<String, BigDecimal> finalMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(placementTest)) {
            for (ComparisonGradesVO comparisonGradesVO : placementTest) {
                if (BigDecimal.ZERO.compareTo(comparisonGradesVO.getTest()) < 0) {
                    comparisonGradesVO.setTestAve(comparisonGradesVO.getTest().divide(comparisonGradesVO.getTestNum(), 2, RoundingMode.HALF_UP));
                }
            }
            placementMap = placementTest.stream().collect(Collectors.toMap(ComparisonGradesVO::getYear, ComparisonGradesVO::getTestAve));
        }
        if (!CollectionUtils.isEmpty(finalTest)) {
            for (ComparisonGradesVO comparisonGradesVO : finalTest) {
                if (BigDecimal.ZERO.compareTo(comparisonGradesVO.getTest()) < 0) {
                    comparisonGradesVO.setTestAve(comparisonGradesVO.getTest().divide(comparisonGradesVO.getTestNum(), 2, RoundingMode.HALF_UP));
                }
            }
            finalMap = finalTest.stream().collect(Collectors.toMap(ComparisonGradesVO::getYear, ComparisonGradesVO::getTestAve));
        }
        for (String year : yearList) {
            xAxisData.add(year);
            if (!CollectionUtils.isEmpty(placementMap)) {
                list1.getYAxisData().add(StringUtils.isNotNull(placementMap.get(year)) ? String.valueOf(placementMap.get(year)) : "0");
            } else {
                list1.getYAxisData().add("0");
            }
            if (!CollectionUtils.isEmpty(finalMap)) {
                list2.getYAxisData().add(StringUtils.isNotNull(finalMap.get(year)) ? String.valueOf(finalMap.get(year)) : "0");
            } else {
                list2.getYAxisData().add("0");
            }
        }
        dataList.add(list1);
        dataList.add(list2);
        analysisLineVO.setXAxisData(xAxisData);
        analysisLineVO.setDataList(dataList);
        return analysisLineVO;
    }

    @Override
    public List<LabelAndValueVO> scoreProportion() {
        List<LabelAndValueVO> valueVOList = new ArrayList<>();
        Long unitId = getUnitId();
        if (StringUtils.isNull(unitId)) {
            return valueVOList;
        }
        // 获取子级部门id
        List<Long> unitIdList = unitMapper.juniorUnit(unitId);
        return projectPersonnelInfoMapper.scoreProportion(unitIdList);
    }

    @Override
    public List<LabelAndValueNameVO> expensePersonnel(ExpenseStatisticsDTO dto) {
        List<LabelAndValueNameVO> voList = new ArrayList<>();
        List<Expense> list = expenseMapper.selectList(new LambdaQueryWrapper<Expense>()
                .eq(null != dto.getFlightId(), Expense::getFlightId, dto.getFlightId())
                .eq(null != dto.getTrainingTime(), Expense::getTrainingTime, dto.getTrainingTime())
                .eq(StringUtils.isBlank(dto.getYear()), Expense::getYear, Year.now().getValue())
                .eq(StringUtils.isNotBlank(dto.getYear()), Expense::getYear, dto.getYear()));
        if (CollectionUtils.isEmpty(list)) {
            voList.add(new LabelAndValueNameVO().setName("计划参训人数").setValue("0"));
            voList.add(new LabelAndValueNameVO().setName("实际参训人数").setValue("0"));
            return voList;
        }
        voList.add(new LabelAndValueNameVO()
                .setName("计划参训人数")
                .setValue(list.stream().map(l ->
                                BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getPlannedNumber()) ?
                                        "0" : l.getPlannedNumber())))
                        .reduce(BigDecimal.ZERO, BigDecimal::add).stripTrailingZeros().toPlainString()));
        voList.add(new LabelAndValueNameVO()
                .setName("实际参训人数")
                .setValue(list.stream().map(l ->
                                BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getParticipantsNumber()) ?
                                        "0" : l.getParticipantsNumber())))
                        .reduce(BigDecimal.ZERO, BigDecimal::add).stripTrailingZeros().toPlainString()));
        return voList;
    }

    @Override
    public AnalysisLineVO expenseAmount(ExpenseStatisticsDTO dto) {
        AnalysisLineVO analysisLineVO = new AnalysisLineVO();
        List<AnalysisLineVO.DataList> dataList = new ArrayList<>();
        AnalysisLineVO.DataList list1 = new AnalysisLineVO.DataList();
        list1.setName("机关预算");
        list1.setType("line");
        list1.setYAxisData(new ArrayList<>());
        AnalysisLineVO.DataList list2 = new AnalysisLineVO.DataList();
        list2.setName("承训单位预算");
        list2.setType("line");
        list2.setYAxisData(new ArrayList<>());
        AnalysisLineVO.DataList list3 = new AnalysisLineVO.DataList();
        list3.setName("实际");
        list3.setType("line");
        list3.setYAxisData(new ArrayList<>());
        List<String> xAxisData = new ArrayList<>();
        // 获取当前年份
        List<String> yearList = DateUtils.getYearCollectionExample(6);
        List<Expense> list = expenseMapper.selectList(new LambdaQueryWrapper<Expense>()
                .eq(null != dto.getFlightId(), Expense::getFlightId, dto.getFlightId())
                .eq(null != dto.getTrainingTime(), Expense::getTrainingTime, dto.getTrainingTime())
                .in(Expense::getYear, yearList));
        if (CollectionUtils.isEmpty(list)) {
            return analysisLineVO;
        }
        Map<String, List<Expense>> listMap = list.stream().collect(Collectors.groupingBy(Expense::getYear));
        for (String year : yearList) {
            xAxisData.add(year);
            List<Expense> expenses = listMap.get(year);
            if (CollectionUtils.isEmpty(expenses)) {
                list1.getYAxisData().add("0");
                list2.getYAxisData().add("0");
                list3.getYAxisData().add("0");
            } else {
                list1.getYAxisData().add(expenses.stream().map(l ->
                                BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getOrganBudgetedAmount()) ?
                                        "0" : l.getOrganBudgetedAmount())))
                        .reduce(BigDecimal.ZERO, BigDecimal::add).stripTrailingZeros().toPlainString());
                list2.getYAxisData().add(expenses.stream().map(l ->
                                BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getTrainingBudgetedAmount()) ?
                                        "0" : l.getTrainingBudgetedAmount())))
                        .reduce(BigDecimal.ZERO, BigDecimal::add).stripTrailingZeros().toPlainString());
                list3.getYAxisData().add(expenses.stream().map(l ->
                                BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getSettlementAmount()) ?
                                        "0" : l.getSettlementAmount())))
                        .reduce(BigDecimal.ZERO, BigDecimal::add).stripTrailingZeros().toPlainString());
            }
        }
        dataList.add(list1);
        dataList.add(list2);
        dataList.add(list3);
        analysisLineVO.setXAxisData(xAxisData);
        analysisLineVO.setDataList(dataList);
        return analysisLineVO;
    }

    @Override
    public TypeStatisticsVO expenseType(ExpenseStatisticsDTO dto) {
        TypeStatisticsVO vo = new TypeStatisticsVO();
        List<LabelAndValueNameVO> voList = new ArrayList<>();
        List<Expense> list = expenseMapper.selectList(new LambdaQueryWrapper<Expense>()
                .eq(null != dto.getFlightId(), Expense::getFlightId, dto.getFlightId())
                .eq(null != dto.getTrainingTime(), Expense::getTrainingTime, dto.getTrainingTime())
                .eq(StringUtils.isBlank(dto.getYear()), Expense::getYear, Year.now().getValue())
                .eq(StringUtils.isNotBlank(dto.getYear()), Expense::getYear, dto.getYear()));
        if (CollectionUtils.isEmpty(list)) {
            voList.add(new LabelAndValueNameVO().setName("住宿费用").setValue("0"));
            voList.add(new LabelAndValueNameVO().setName("伙食费用").setValue("0"));
            voList.add(new LabelAndValueNameVO().setName("场地费用").setValue("0"));
            voList.add(new LabelAndValueNameVO().setName("其他费用").setValue("0"));
            voList.add(new LabelAndValueNameVO().setName("总费用").setValue("0"));
            vo.setTotal("0");
            vo.setLabels(voList);
            return vo;
        }
        voList.add(new LabelAndValueNameVO()
                .setName("住宿费用")
                .setValue(list.stream().map(l ->
                        BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getAccommodationCost()) ?
                                "0" : l.getAccommodationCost()))
                ).reduce(BigDecimal.ZERO, BigDecimal::add).stripTrailingZeros().toPlainString()));
        voList.add(new LabelAndValueNameVO()
                .setName("伙食费用")
                .setValue(list.stream().map(l ->
                        BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getBoardMoney()) ?
                                "0" : l.getBoardMoney()))
                ).reduce(BigDecimal.ZERO, BigDecimal::add).stripTrailingZeros().toPlainString()));
        voList.add(new LabelAndValueNameVO()
                .setName("场地费用")
                .setValue(list.stream().map(l ->
                        BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getConferenceRoom()) ?
                                        "0" : l.getConferenceRoom()))
                                .add(BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getProductionWorkshop()) ?
                                        "0" : l.getProductionWorkshop())))
                ).reduce(BigDecimal.ZERO, BigDecimal::add).stripTrailingZeros().toPlainString()));
        voList.add(new LabelAndValueNameVO()
                .setName("其他费用")
                .setValue(list.stream().map(l ->
                        BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getOtherExpenses()) ?
                                "0" : l.getOtherExpenses()))
                ).reduce(BigDecimal.ZERO, BigDecimal::add).stripTrailingZeros().toPlainString()));
        vo.setTotal(list.stream().map(Expense::getTotal).reduce(BigDecimal.ZERO, BigDecimal::add).stripTrailingZeros().toPlainString());
        vo.setLabels(voList);
        return vo;
    }

    @Override
    public TypeStatisticsVO expenseUnit(ExpenseStatisticsDTO dto) {
        TypeStatisticsVO vo = new TypeStatisticsVO();
        List<LabelAndValueNameVO> voList = new ArrayList<>();
        List<Expense> list = expenseMapper.selectList(new LambdaQueryWrapper<Expense>()
                .eq(null != dto.getFlightId(), Expense::getFlightId, dto.getFlightId())
                .eq(null != dto.getTrainingTime(), Expense::getTrainingTime, dto.getTrainingTime())
                .eq(StringUtils.isNotBlank(dto.getYear()), Expense::getYear, dto.getYear())
                .eq(StringUtils.isBlank(dto.getYear()), Expense::getYear, Year.now().getValue()));
        if (CollectionUtils.isEmpty(list)) {
            return vo;
        }
        Map<String, List<Expense>> map = list.stream().collect(Collectors.groupingBy(Expense::getTrainingUnitName));
        BigDecimal bigDecimal = BigDecimal.ZERO;
        for (String m : map.keySet()) {
            BigDecimal reduce = map.get(m).stream().map(l ->
                    BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getAccommodationCost()) ?
                            "0" : l.getAccommodationCost()))).reduce(BigDecimal.ZERO, BigDecimal::add).stripTrailingZeros();
            voList.add(new LabelAndValueNameVO()
                    .setName(m)
                    .setValue(reduce.toPlainString()));
            bigDecimal.add(reduce);
        }
        vo.setTotal(bigDecimal.stripTrailingZeros().toPlainString());
        vo.setLabels(voList);
        return vo;
    }

    @Override
    public TypeStatisticsVO expenseOperations(ExpenseStatisticsDTO dto) {
        TypeStatisticsVO vo = new TypeStatisticsVO();
        List<Expense> list = expenseMapper.selectList(new LambdaQueryWrapper<Expense>()
                .eq(null != dto.getFlightId(), Expense::getFlightId, dto.getFlightId())
                .eq(StringUtils.isBlank(dto.getYear()), Expense::getYear, Year.now().getValue())
                .eq(StringUtils.isNotBlank(dto.getYear()), Expense::getYear, dto.getYear()));
        if (CollectionUtils.isEmpty(list)) {
            return vo;
        }
        // List<Unit> unitList = unitMapper.selectList(new LambdaQueryWrapper<Unit>().eq(Unit::getParentId, getUnitId()));
        // Map<Long, String> map = unitList.stream().collect(Collectors.toMap(Unit::getUnitId, Unit::getUnitName));
        // projectMapper.selectList(new LambdaQueryWrapper<Project>().in())
        // BigDecimal bigDecimal = BigDecimal.ZERO;
        // map.keySet().forEach(m ->{
        //     BigDecimal reduce = map.get(m).stream().map(l ->
        //             BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getAccommodationCost()) ?
        //                     "0" : l.getAccommodationCost()))).reduce(BigDecimal.ZERO, BigDecimal::add);
        //     voList.add(new LabelAndValueNameVO()
        //             .setName(m)
        //             .setValue(String.valueOf(reduce)));
        //     bigDecimal.add(reduce);
        // });
        //
        // voList.add(new LabelAndValueNameVO()
        //         .setName("总费用")
        //         .setValue(String.valueOf(bigDecimal)));
        return vo;
    }

    @Override
    public AnalysisLineVO expensePerCapita(ExpenseStatisticsDTO dto) {
        AnalysisLineVO analysisLineVO = new AnalysisLineVO();
        List<AnalysisLineVO.DataList> dataList = new ArrayList<>();
        AnalysisLineVO.DataList list1 = new AnalysisLineVO.DataList();
        list1.setName("机关预算");
        list1.setType("line");
        list1.setYAxisData(new ArrayList<>());
        AnalysisLineVO.DataList list2 = new AnalysisLineVO.DataList();
        list2.setName("承训单位预算");
        list2.setType("line");
        list2.setYAxisData(new ArrayList<>());
        AnalysisLineVO.DataList list3 = new AnalysisLineVO.DataList();
        list3.setName("实际");
        list3.setType("line");
        list3.setYAxisData(new ArrayList<>());
        List<String> xAxisData = new ArrayList<>();
        // 获取当前年份
        List<String> yearList = DateUtils.getYearCollectionExample(6);
        List<Expense> list = expenseMapper.selectList(new LambdaQueryWrapper<Expense>()
                .eq(null != dto.getFlightId(), Expense::getFlightId, dto.getFlightId())
                .eq(null != dto.getTrainingTime(), Expense::getTrainingTime, dto.getTrainingTime())
                .in(Expense::getYear, yearList));
        if (CollectionUtils.isEmpty(list)) {
            return analysisLineVO;
        }
        // Long count = projectPersonnelInfoMapper.selectCount(new LambdaQueryWrapper<ProjectPersonnelInfo>()
        //         .eq(null != dto.getTrainingTime(), ProjectPersonnelInfo::getTrainingTime, dto.getTrainingTime())
        //         .eq(null != dto.getFlightId(), ProjectPersonnelInfo::getFlightId, dto.getFlightId()));
        Map<String, List<Expense>> listMap = list.stream().collect(Collectors.groupingBy(Expense::getYear));
        for (String year : yearList) {
            xAxisData.add(year);
            List<Expense> expenses = listMap.get(year);
            if (CollectionUtils.isEmpty(expenses)) {
                list1.getYAxisData().add("0");
                list2.getYAxisData().add("0");
                list3.getYAxisData().add("0");
            } else {
                BigDecimal reduce = expenses.stream().map(l ->
                                BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getParticipantsNumber()) ?
                                        "0" : l.getParticipantsNumber())))
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                list1.getYAxisData().add(expenses.stream().map(l ->
                                BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getOrganBudgetedAmount()) ?
                                        "0" : l.getOrganBudgetedAmount())))
                        .reduce(BigDecimal.ZERO, BigDecimal::add)
                        .divide(reduce, 2, RoundingMode.HALF_UP).toPlainString());
                list2.getYAxisData().add(expenses.stream().map(l ->
                                BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getTrainingBudgetedAmount()) ?
                                        "0" : l.getTrainingBudgetedAmount())))
                        .reduce(BigDecimal.ZERO, BigDecimal::add)
                        .divide(reduce, 2, RoundingMode.HALF_UP).toPlainString());
                list3.getYAxisData().add(expenses.stream().map(l ->
                                BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getSettlementAmount()) ?
                                        "0" : l.getSettlementAmount())))
                        .reduce(BigDecimal.ZERO, BigDecimal::add)
                        .divide(reduce, 2, RoundingMode.HALF_UP).toPlainString());
            }
        }
        dataList.add(list1);
        dataList.add(list2);
        dataList.add(list3);
        analysisLineVO.setXAxisData(xAxisData);
        analysisLineVO.setDataList(dataList);
        return analysisLineVO;
    }


    @Override
    public NumberParticipantsVO flightNumberParticipants(ExpenseStatisticsDTO dto) {
        NumberParticipantsVO numberParticipantsVO = new NumberParticipantsVO();

        if (StringUtils.isNotNull(dto.getFlightId())) {
            Flight flight = flightMapper.selectVoById(dto.getFlightId());
            if (StringUtils.isNull(flight)) {
                return numberParticipantsVO;
            }
            numberParticipantsVO.setFlightName(flight.getFlightName() + "班");
            // 获取计划参训人数
        } else {
            if (StringUtils.isEmpty(dto.getYear())) {
                dto.setYear(DateUtils.dateTimeNow("YYYY"));
            }
            numberParticipantsVO.setFlightName(dto.getYear() + "年");
        }
        Long unitId = getUnitId();
        if (StringUtils.isNull(unitId)) {
            return numberParticipantsVO;
        }
        // 获取子级部门id
        List<Long> unitIdList = unitMapper.juniorUnit(unitId);
        unitIdList.remove(unitId);
        // 获取当前年份
        List<String> yearList = DateUtils.getYearsBefore(Integer.parseInt(dto.getYear()), 1);
        // 获取计划参训人数
        Integer planParticipate = projectMapper.getPlanParticipateNum(unitIdList, yearList, dto.getFlightId());
        numberParticipantsVO.setPlanParticipate(planParticipate);
        // 获取实际参训人数
        Integer actualParticipate = projectPersonnelInfoMapper.getActualParticipateNum(unitIdList, yearList, dto.getFlightId());
        numberParticipantsVO.setActualParticipate(actualParticipate);
        return numberParticipantsVO;
    }

    @Override
    public AnalysisLineVO flightTrainingCourseNum(ExpenseStatisticsDTO dto) {
        AnalysisLineVO analysisLineVO = new AnalysisLineVO();
        // 判断是否传年份
        if (StringUtils.isEmpty(dto.getYear())) {
            dto.setYear(DateUtils.dateTimeNow("YYYY"));
        }
        Long unitId = SecurityUtils.getUnitId();
        if (StringUtils.isNull(unitId)) {
            return analysisLineVO;
        }
        // 获取子级部门id
//        List<Long> unitIdList = unitMapper.juniorUnit(unitId);
        List<Long> unitIdList = new ArrayList<>();
        List<AnalysisLineVO.DataList> dataList = new ArrayList<>();
        AnalysisLineVO.DataList list = new AnalysisLineVO.DataList();
        list.setName("培训班数量");
        list.setType("line");
        list.setYAxisData(new ArrayList<>());
        List<String> xAxisData = new ArrayList<>();

        // 获取年份
        List<String> yearList = DateUtils.getYearsBefore(Integer.parseInt(dto.getYear()), 6);
        List<LabelAndValueVO> labelAndValueList = projectMapper.flightTrainingCourseNum(unitIdList, yearList);
        Map<String, String> map = new HashMap<>();
        if (!CollectionUtils.isEmpty(labelAndValueList)) {
            map = labelAndValueList.stream().collect(Collectors.toMap(LabelAndValueVO::getValue, LabelAndValueVO::getLabel));
        }
        for (String year : yearList) {
            xAxisData.add(year);
            if (!CollectionUtils.isEmpty(map)) {
                list.getYAxisData().add(StringUtils.isNotEmpty(map.get(year)) ? map.get(year) : "0");
            } else {
                list.getYAxisData().add("0");
            }
        }
        dataList.add(list);
        analysisLineVO.setXAxisData(xAxisData);
        analysisLineVO.setDataList(dataList);
        return analysisLineVO;
    }

    @Override
    public List<LabelAndValueVO> flightNumProportion(ExpenseStatisticsDTO dto) {
        // 判断是否传年份
        if (StringUtils.isEmpty(dto.getYear())) {
            dto.setYear(DateUtils.dateTimeNow("YYYY"));
        }
        Long unitId = SecurityUtils.getUnitId();
        if (StringUtils.isNull(unitId)) {
            return new ArrayList<>();
        }
        // 获取年份
        List<String> yearList = DateUtils.getYearsBefore(Integer.parseInt(dto.getYear()), 1);
        // 获取子级部门id
//        List<Long> unitIdList = unitMapper.juniorUnit(unitId);
        List<Long> unitIdList = new ArrayList<>();
        return projectMapper.flightNumProportion(unitIdList, yearList);

    }

    @Override
    public FlightTrainingStatusVO flightTrainingStatus(ExpenseStatisticsDTO dto) {
        FlightTrainingStatusVO flightTrainingStatusVO = new FlightTrainingStatusVO();
        if (StringUtils.isEmpty(dto.getYear())) {
            dto.setYear(DateUtils.dateTimeNow("YYYY"));
        }
        Long unitId = SecurityUtils.getUnitId();
        if (StringUtils.isNull(unitId)) {
            return flightTrainingStatusVO;
        }
        // 获取年份
        List<String> yearList = DateUtils.getYearsBefore(Integer.parseInt(dto.getYear()), 1);
        // 获取子级部门id
//        List<Long> unitIdList = unitMapper.juniorUnit(unitId);
        List<Long> unitIdList = new ArrayList<>();
        List<LabelAndValueVO> labelAndValueList = projectPersonnelInfoMapper.FlightTrainingStatusVO(yearList, unitIdList);
        if (!CollectionUtils.isEmpty(labelAndValueList)) {
            int total = labelAndValueList.stream()
                    .mapToInt(labelAndValue -> {
                        try {
                            return Integer.parseInt(labelAndValue.getValue());  // 将字符串转换为整数
                        } catch (NumberFormatException e) {
                            return 0;  // 如果无法解析为整数，返回 0
                        }
                    })
                    .sum();
            flightTrainingStatusVO.setTotal(total);
            flightTrainingStatusVO.setLabels(labelAndValueList);
        }
        return flightTrainingStatusVO;
    }

    @Override
    public List<LabelAndValueVO> flightTrainingType(ExpenseStatisticsDTO dto) {
        if (StringUtils.isEmpty(dto.getYear())) {
            dto.setYear(DateUtils.dateTimeNow("YYYY"));
        }
        Long unitId = SecurityUtils.getUnitId();
        if (StringUtils.isNull(unitId)) {
            return new ArrayList<>();
        }
        // 获取年份
        List<String> yearList = DateUtils.getYearsBefore(Integer.parseInt(dto.getYear()), 1);
        // 获取子级部门id
//        List<Long> unitIdList = unitMapper.juniorUnit(unitId);
        List<Long> unitIdList = new ArrayList<>();
        return flightMapper.flightTrainingType(dto.getYear(), unitIdList);
    }

    @Override
    public AnalysisLineVO flightDistributionTrainees(ExpenseStatisticsDTO dto) {
        AnalysisLineVO analysisLineVO = new AnalysisLineVO();
        if (StringUtils.isNull(dto.getFlightId())) {
            return analysisLineVO;
        }
        if (StringUtils.isEmpty(dto.getYear())) {
            dto.setYear(DateUtils.dateTimeNow("YYYY"));
        }
        List<AnalysisLineVO.DataList> dataList = new ArrayList<>();
        AnalysisLineVO.DataList list1 = new AnalysisLineVO.DataList();
        list1.setName("计划");
        list1.setType("line");
        list1.setYAxisData(new ArrayList<>());
        AnalysisLineVO.DataList list2 = new AnalysisLineVO.DataList();
        list2.setName("实际");
        list2.setType("line");
        list2.setYAxisData(new ArrayList<>());
        List<String> xAxisData = new ArrayList<>();
        List<Unit> units = unitMapper.selectList(new LambdaQueryWrapper<Unit>()
                .eq(Unit::getParentId, getUnitId()));
        if (CollectionUtils.isEmpty(units)) {
            return analysisLineVO;
        }
        for (Unit unit : units) {
            xAxisData.add(unit.getUnitName());
            List<Project> list = projectMapper.selectList(new LambdaQueryWrapper<Project>()
                    .eq(Project::getCreateDept, unit.getUnitId())
                    .eq(Project::getYear, dto.getYear()));
            if (org.apache.commons.collections4.CollectionUtils.isEmpty(list)) {
                list1.getYAxisData().add("0");
                list2.getYAxisData().add("0");
            } else {
                list1.getYAxisData().add(list.stream().map(l ->
                                BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getTrainingPost()) ?
                                        "0" : l.getTrainingPost())))
                        .reduce(BigDecimal.ZERO, BigDecimal::add).stripTrailingZeros().toPlainString());
                List<Long> ids = new ArrayList<>(list.stream().map(Project::getProjectId).toList());
                List<Project> all = getAll(ids);
                ids.addAll(all.stream().map(Project::getProjectId).toList());
                List<ProjectPersonnelInfo> list3 = projectPersonnelInfoMapper.selectList(new LambdaQueryWrapper<ProjectPersonnelInfo>()
                        .in(ProjectPersonnelInfo::getProjectId, ids));
                list2.getYAxisData().add(String.valueOf(list3.size()));
            }
        }
        dataList.add(list1);
        dataList.add(list2);
        analysisLineVO.setXAxisData(xAxisData);
        analysisLineVO.setDataList(dataList);

        return analysisLineVO;
    }

    @Override
    public FlightDistributionProportionVO flightDistributionProportion(ExpenseStatisticsDTO dto) {
        FlightDistributionProportionVO proportionVO = new FlightDistributionProportionVO();
        if (StringUtils.isNull(dto.getFlightId())) {
            return proportionVO;
        }
        if (StringUtils.isEmpty(dto.getYear())) {
            dto.setYear(DateUtils.dateTimeNow("YYYY"));
        }
        List<LabelAndValueVO> labelAndValueList = projectPersonnelInfoMapper.flightDistributionProportion(dto.getFlightId(), dto.getYear());
        if (!CollectionUtils.isEmpty(labelAndValueList)) {
            int total = labelAndValueList.stream()
                    .mapToInt(labelAndValue -> {
                        try {
                            return Integer.parseInt(labelAndValue.getValue());  // 将字符串转换为整数
                        } catch (NumberFormatException e) {
                            return 0;  // 如果无法解析为整数，返回 0
                        }
                    })
                    .sum();
            proportionVO.setTotal(total);
            proportionVO.setLabels(labelAndValueList);
        }
        return proportionVO;
    }

    @Override
    public AnalysisLineVO flightAnnualExcellenceRate(ExpenseStatisticsDTO dto) {
        AnalysisLineVO analysisLineVO = new AnalysisLineVO();
        List<AnalysisLineVO.DataList> dataList = new ArrayList<>();
        AnalysisLineVO.DataList list = new AnalysisLineVO.DataList();
        list.setName("历年优秀率");
        list.setType("line");
        list.setYAxisData(new ArrayList<>());
        List<String> xAxisData = new ArrayList<>();
        if (StringUtils.isNull(dto.getFlightId())) {
            return analysisLineVO;
        }
        // 获取当前班次的班次类型
        Flight flight = flightMapper.selectById(dto.getFlightId());
        if (StringUtils.isNull(flight) || StringUtils.isNull(flight.getMajorType())) {
            return analysisLineVO;
        }
        String majorType = flight.getMajorType();
        if (StringUtils.isEmpty(dto.getYear())) {
            dto.setYear(DateUtils.dateTimeNow("YYYY"));
        }
        // 获取年份
        List<String> yearList = DateUtils.getYearsBefore(Integer.parseInt(dto.getYear()), 6);
        List<LabelAndValueVO> flightAnnualExcellenceRateList = projectPersonnelInfoMapper.flightAnnualExcellenceRate(yearList, majorType);
        Map<String, String> map = new HashMap<>();
        if (!CollectionUtils.isEmpty(flightAnnualExcellenceRateList)) {
            map = flightAnnualExcellenceRateList.stream().collect(Collectors.toMap(LabelAndValueVO::getValue, LabelAndValueVO::getLabel));
        }
        for (String year : yearList) {
            xAxisData.add(year);
            if (!CollectionUtils.isEmpty(map)) {
                list.getYAxisData().add(StringUtils.isNotEmpty(map.get(year)) ? map.get(year) : "0");
            } else {
                list.getYAxisData().add("0");
            }
        }
        dataList.add(list);
        analysisLineVO.setXAxisData(xAxisData);
        analysisLineVO.setDataList(dataList);
        return analysisLineVO;
    }

    @Override
    public List<LabelAndValueVO> flightProportionGrades(ExpenseStatisticsDTO dto) {
        if (StringUtils.isNull(dto.getFlightId())) {
            return new ArrayList<>();
        }
        if (StringUtils.isEmpty(dto.getYear())) {
            dto.setYear(DateUtils.dateTimeNow("YYYY"));
        }
        // 获取年份
        List<String> yearList = DateUtils.getYearsBefore(Integer.parseInt(dto.getYear()), 1);
        return projectPersonnelInfoMapper.flightProportionGrades(yearList, dto.getFlightId());
    }

    @Override
    public AnalysisLineVO flightExpenseSettlement(ExpenseStatisticsDTO dto) {
        AnalysisLineVO analysisLineVO = new AnalysisLineVO();
        List<AnalysisLineVO.DataList> dataList = new ArrayList<>();
        AnalysisLineVO.DataList list = new AnalysisLineVO.DataList();
        list.setName("预算");
        list.setType("column");
        list.setYAxisData(new ArrayList<>());
        AnalysisLineVO.DataList list1 = new AnalysisLineVO.DataList();
        list1.setName("结算");
        list1.setType("column");
        list1.setYAxisData(new ArrayList<>());
        List<String> xAxisData = new ArrayList<>();
        if (StringUtils.isNull(dto.getFlightId())) {
            return analysisLineVO;
        }
        // 获取当前班次的班次类型
        Flight flight = flightMapper.selectById(dto.getFlightId());
        if (StringUtils.isNull(flight) || StringUtils.isNull(flight.getMajorType())) {
            return analysisLineVO;
        }
        String majorType = flight.getMajorType();
        if (StringUtils.isEmpty(dto.getYear())) {
            dto.setYear(DateUtils.dateTimeNow("YYYY"));
        }
        // 获取年份
        List<String> yearList = DateUtils.getYearsBefore(Integer.parseInt(dto.getYear()), 6);
        // 获取预算费用
        List<LabelAndValueVO> estimatedCostList = demandMapper.estimatedCost(majorType, yearList);
        Map<String, String> estimatedCostMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(estimatedCostList)) {
            estimatedCostMap = estimatedCostList.stream().collect(Collectors.toMap(LabelAndValueVO::getValue, LabelAndValueVO::getLabel));
        }
        // 获取结算费用
        List<LabelAndValueVO> settlementCostList = demandMapper.settlementCost(majorType, yearList);
        Map<String, String> settlementCostMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(settlementCostList)) {
            settlementCostMap = settlementCostList.stream().collect(Collectors.toMap(LabelAndValueVO::getValue, LabelAndValueVO::getLabel));
        }
        for (String year : yearList) {
            xAxisData.add(year);
            if (!CollectionUtils.isEmpty(estimatedCostMap)) {
                list.getYAxisData().add(StringUtils.isNotEmpty(estimatedCostMap.get(year)) ? estimatedCostMap.get(year) : "0");
            } else {
                list.getYAxisData().add("0");
            }
            if (!CollectionUtils.isEmpty(settlementCostMap)) {
                list1.getYAxisData().add(StringUtils.isNotEmpty(settlementCostMap.get(year)) ? settlementCostMap.get(year) : "0");
            } else {
                list1.getYAxisData().add("0");
            }
        }
        dataList.add(list);
        dataList.add(list1);
        analysisLineVO.setXAxisData(xAxisData);
        analysisLineVO.setDataList(dataList);
        return analysisLineVO;
    }


    public List<Project> getAll(List<Long> ids) {
        List<Project> list = new ArrayList<>();
        List<Project> projects = projectMapper.selectList(new LambdaQueryWrapper<Project>()
                .in(Project::getParentId, ids));
        if (CollectionUtils.isEmpty(projects)) {
            return list;
        }
        list.addAll(projects);
        list.addAll(getAll(projects.stream().map(Project::getProjectId).distinct().toList()));
        return list;
    }
}
