package com.kcim.service.impl;

import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.afterturn.easypoi.util.PoiCellUtil;
import cn.afterturn.easypoi.util.PoiMergeCellUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.ImmutableMap;
import com.kcim.common.constants.*;
import com.kcim.common.enums.CustomSqlTypeEnum;
import com.kcim.common.enums.DateStyleEnum;
import com.kcim.common.enums.ErrorCodeEnum;
import com.kcim.common.exception.CostException;
import com.kcim.common.file.MinioConfig;
import com.kcim.common.file.MinioFileUtil;
import com.kcim.common.util.*;
import com.kcim.common.util.excel.ExcelPoiUtil;
import com.kcim.common.util.excel.entity.ColEntity;
import com.kcim.common.util.excel.entity.TitleEntity;
import com.kcim.dao.mapper.CostDepartmentProfitMapper;
import com.kcim.dao.model.*;
import com.kcim.dao.repository.*;
import com.kcim.service.*;
import com.kcim.vo.*;
import com.kcim.web.reponse.BatchCostProfitResponse;
import com.kcim.web.reponse.ComputeProfitCollectResponse;
import com.kcim.web.reponse.CostProfitRedirectResponse;
import com.kcim.web.reponse.ProfitReportResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static com.kcim.common.constants.Constant.PROFIT_REPORT_TYPE;
import static com.kcim.common.constants.ParameterConstant.MEDICAL_TECHNIQUES_SHARE_LEVEL_ID;


@Service("costDepartmentProfitService")
@Slf4j
@AllArgsConstructor
public class CostDepartmentProfitServiceImpl extends BaseBatchServiceImpl<CostDepartmentProfitMapper, CostDepartmentProfit> implements CostDepartmentProfitService {

//    @Value("${file.filelocal}")
//    private String hospProfitReportUrl;
//
//    @Value("${file.serverUrl}")
//    private String serverUrl;

    private final ReportFormService reportFormService;

    private final IncomeCollectionService incomeCollectionService;

    private final CostShareLevelService costShareLevelService;

    private final ResponsibilityService responsibilityService;

    private final ReportRelationService reportRelationService;

    private final AllocationService allocationService;

    private final AllocationQueryService allocationQueryService;

    private final FileRecordService fileRecordService;

    private final MinioConfig minioConfig;

    private final MinioFileUtil minioFileUtil;

    private final CenterService centerService;

    private final CostDepartmentProfitRepository costDepartmentProfitRepository;

    private final ComputeLastProfitDateRepository computeLastProfitDateRepository;

    private final AccountingService accountingService;

    private final CostAccountShareService costAccountShareService;

    private final UserResponsibilityRightService userResponsibilityRightService;

    ResponsibilityRepository responsibilityRepository;

    CostDepartmentProfitAccountRepository costDepartmentProfitAccountRepository;
    AccountingRepository accountingRepository;

    private final SqlService sqlService;
    private final String AMOUNT = "金额";

    private final String PERCENT = "占比";

    private final String AMOUNT_FIELD = "amount";

    private final String PERCENT_FIELD = "percent";
//
//    public CostDepartmentProfitServiceImpl(ReportFormService reportFormService, IncomeCollectionService incomeCollectionService, CostShareLevelService costShareLevelService, ResponsibilityService responsibilityService, ReportRelationService reportRelationService, AllocationService allocationService, AllocationQueryService allocationQueryService, FileRecordService fileRecordService, MinioConfig minioConfig, MinioFileUtil minioFileUtil, CenterService centerService, CostDepartmentProfitRepository costDepartmentProfitRepository, ComputeLastProfitDateRepository computeLastProfitDateRepository, AccountingService accountingService, CostAccountShareService costAccountShareService, SqlService sqlService, UserResponsibilityRightService userResponsibilityRightService) {
//        this.reportFormService = reportFormService;
//        this.incomeCollectionService = incomeCollectionService;
//        this.costShareLevelService = costShareLevelService;
//        this.responsibilityService = responsibilityService;
//        this.reportRelationService = reportRelationService;
//        this.allocationService = allocationService;
//        this.allocationQueryService = allocationQueryService;
//        this.fileRecordService = fileRecordService;
//        this.minioConfig = minioConfig;
//        this.minioFileUtil = minioFileUtil;
//        this.centerService = centerService;
//        this.costDepartmentProfitRepository = costDepartmentProfitRepository;
//        this.computeLastProfitDateRepository = computeLastProfitDateRepository;
//        this.accountingService = accountingService;
//        this.costAccountShareService = costAccountShareService;
//        this.sqlService = sqlService;
//        this.userResponsibilityRightService = userResponsibilityRightService;
//    }

    /**
     * 查询科室损益数据
     *
     * @param current
     * @param pageSize
     * @param responsibilityCode
     * @param date
     * @param hospId
     * @return
     */
    @Override
    public PageUtils queryList(Integer current, Integer pageSize, String responsibilityCode, String date, Long hospId) {
        int year = 0;
        int month = 0;
        if (StrUtil.isNotBlank(date)) {
            Date dateTime = DateUtils.StringToDate(date, DateStyleEnum.YYYY_MM_DD);
            year = DateUtil.year(dateTime);
            month = DateUtil.month(dateTime) + 1;

        }
        Page<CostDepartmentProfit> departmentProfitPage = new Page<>(current, pageSize);
        // 查询的时候过过滤那些计算方式是不设置的数据
        Page<CostDepartmentProfit> pages = this.page(departmentProfitPage, new QueryWrapper<CostDepartmentProfit>().lambda()
                .eq(CostDepartmentProfit::getHospId, hospId)
                .eq(StrUtil.isNotBlank(responsibilityCode), CostDepartmentProfit::getResponsibilityCode, responsibilityCode)
                .eq(StrUtil.isNotBlank(date), CostDepartmentProfit::getYear, year)
                .eq(StrUtil.isNotBlank(date), CostDepartmentProfit::getMonth, month)
                .ne(CostDepartmentProfit::getCalcType, NumberConstant.ZERO).orderByDesc(CostDepartmentProfit::getAmount));
        List<CostDepartmentProfit> records = pages.getRecords();
        List<CostDepartmentProfitVO> costDepartmentProfitVOList = BeanUtil.convertList(records, CostDepartmentProfitVO.class);
        DecimalFormat df = new DecimalFormat("0.00%");
        for (CostDepartmentProfitVO costDepartmentProfitVO : costDepartmentProfitVOList) {
            if (costDepartmentProfitVO.getPercent() != null) {
                costDepartmentProfitVO.setPercentName(df.format(costDepartmentProfitVO.getPercent()));
            }
        }
        PageUtils pageUtils = new PageUtils(pages);
        pageUtils.setList(costDepartmentProfitVOList);
        return pageUtils;
    }

    /**
     * 科室损益计算
     *
     * @param date
     * @param hospId
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    public void setDepartmentProfit(String date, Long hospId) {
        DateTime parse = DateUtil.parse(date);
        int year = DateUtil.year(parse);
        int month = DateUtil.month(parse) + 1;
        // 先查询指定条件的报表数据  查询损益表的数据
        List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
                .eq(ReportForm::getHospId, hospId)
                .eq(ReportForm::getReportType, NumberConstant.ZERO));
        if (CollUtil.isEmpty(reportFormList)) {
            throw new CostException(500, "损益表未找到");
        }
        // 遍历报表数据根据报表数据计算方式进行计算


        //这里拆分成两个 原有的最后一层 以及 参数医技

        // 查询最后一个层级的责任中心
        List<CostShareLevel> costShareLevelList = costShareLevelService.list(new QueryWrapper<CostShareLevel>().lambda()
                .eq(CostShareLevel::getHospId, hospId).orderByDesc(CostShareLevel::getLeverSort));
        if (CollUtil.isEmpty(costShareLevelList)) {
            throw new CostException(500, "分摊层级未设置");
        }
        // TODO 可能多个
        Long id = costShareLevelList.get(0).getId();
        // 查询责任中心里面是这个层级的所有的收益中心
        List<Responsibility> responsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
                .eq(Responsibility::getHospId, hospId).eq(Responsibility::getResponsibilityType, NumberConstant.ONE).eq(Responsibility::getShareId, id));

        //通过参数获取医技成分摊层级id
        CommonParameterVo parameter = centerService.getParameter(MEDICAL_TECHNIQUES_SHARE_LEVEL_ID);


        // 归集后
        List<IncomeCollection> incomeList = incomeCollectionService.list(new QueryWrapper<IncomeCollection>().lambda()
                .eq(IncomeCollection::getHospId, hospId)
                .eq(year > 0, IncomeCollection::getYear, year).eq(month > 0, IncomeCollection::getMonth, month));
        if (CollUtil.isEmpty(incomeList)) {
            throw new CostException(500, "归集后数据不存在");
        }
        Map<Long, List<ReportRelation>> reportRelationMap = reportRelationService.list(new QueryWrapper<ReportRelation>().lambda().eq(ReportRelation::getHospId, hospId)).stream().collect(Collectors.groupingBy(ReportRelation::getReportId));
        // 分摊后的数据说明是分摊后的数据 这里原有为收益中心数据 同步添加医技分摊后数据
        List<AllocationQuery> allocationQueryList = allocationQueryService.list(new QueryWrapper<AllocationQuery>().lambda()
                .eq(AllocationQuery::getHospId, hospId)
                .eq(year > 0, AllocationQuery::getDateYear, year)
                .eq(month > 0, AllocationQuery::getDateMonth, month)
                .eq(AllocationQuery::getShareType, NumberConstant.ONE)
        );
        if (CollUtil.isEmpty(allocationQueryList)) {
            throw new CostException(500, "分摊后数据不存在");
        }
        //获取医技分摊后数据
        List<AllocationQuery> medicalTechniquesAllocationQueryList = allocationQueryService.list(new QueryWrapper<AllocationQuery>().lambda()
                .eq(AllocationQuery::getHospId, hospId)
                .eq(year > 0, AllocationQuery::getDateYear, year)
                .eq(month > 0, AllocationQuery::getDateMonth, month)
                .eq(AllocationQuery::getShareType, NumberConstant.TWO)
        );
        // 封装数据
        List<AllocationQueryReportVO> allocationQueryReportVOList = BeanUtil.convertList(allocationQueryList, AllocationQueryReportVO.class);
        allocationQueryReportVOList.forEach(i -> {
            i.setAccountingCodes(Arrays.asList(i.getAccountingCode().split(StrUtil.COMMA)));
            i.setAccountingNames(Arrays.asList(i.getAccountingName().split(StrUtil.COMMA)));
        });
        List<AllocationQueryReportVO> medicalTechniquesAllocationQueryReportVOList = BeanUtil.convertList(medicalTechniquesAllocationQueryList, AllocationQueryReportVO.class);
        medicalTechniquesAllocationQueryReportVOList.forEach(i -> {
            i.setAccountingCodes(Arrays.asList(i.getAccountingCode().split(StrUtil.COMMA)));
            i.setAccountingNames(Arrays.asList(i.getAccountingName().split(StrUtil.COMMA)));
        });
        // 查询分摊的报表数据 后面的计算方式需要使用 小计等需要使用
        List<Allocation> allocationList = allocationService.list(new QueryWrapper<Allocation>().lambda().eq(Allocation::getHospId, hospId)
                .eq(year > 0, Allocation::getDateYear, year).eq(month > 0, Allocation::getDateMonth, month));
        if (CollUtil.isEmpty(allocationList)) {
            throw new CostException(500, "分摊报表数据不存在");
        }

        // 查询所有指定类型的损益表
        // 每个责任中心对应报表都要生成记录
        // 封装需要设置的数据
        List<CostDepartmentProfitVO> list = getCostDepartmentProfitVOS(hospId, year, month, reportFormList, costShareLevelList, responsibilityList, incomeList, reportRelationMap, allocationQueryReportVOList, allocationList, NumberConstant.ONE);


        // 删除这个年月的数据
        this.remove(new QueryWrapper<CostDepartmentProfit>().lambda().eq(CostDepartmentProfit::getHospId, hospId)
                .eq(CostDepartmentProfit::getYear, year).eq(CostDepartmentProfit::getMonth, month));
        // 添加数据
        List<CostDepartmentProfit> costDepartmentProfits = BeanUtil.convertList(list, CostDepartmentProfit.class);
        if (Objects.nonNull(parameter)) {
            String value = parameter.getValue();
            if (StringUtils.isEmpty(value)) {
                throw new CostException("医技成分摊层级id参数未设置");
            }
            // 查询责任中心里面是医技分摊层级的
            List<Responsibility> medicalTechniquesResponsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
                    .eq(Responsibility::getHospId, hospId).eq(Responsibility::getShareId, value));
            List<CostDepartmentProfitVO> medicalTechniquesList = getCostDepartmentProfitVOS(hospId, year, month, reportFormList, costShareLevelList, medicalTechniquesResponsibilityList, incomeList, reportRelationMap, medicalTechniquesAllocationQueryReportVOList, allocationList, NumberConstant.TWO);

            List<CostDepartmentProfit> medicalTechniquesCostDepartmentProfits = BeanUtil.convertList(medicalTechniquesList, CostDepartmentProfit.class);
            if (!CollectionUtils.isEmpty(medicalTechniquesCostDepartmentProfits)) {
                costDepartmentProfits.addAll(medicalTechniquesCostDepartmentProfits);
            }
        }
        long l = System.currentTimeMillis();
        costDepartmentProfits.forEach(i -> {
            i.setCreateTime(l);
        });

        this.saveBatch(costDepartmentProfits);
    }

    private List<CostDepartmentProfitVO> getCostDepartmentProfitVOS(Long hospId, int year, int month, List<ReportForm> reportFormList,
                                                                    List<CostShareLevel> costShareLevelList, List<Responsibility> responsibilityList,
                                                                    List<IncomeCollection> incomeList, Map<Long, List<ReportRelation>> reportRelationMap,
                                                                    List<AllocationQueryReportVO> allocationQueryReportVOList, List<Allocation> allocationList, Integer shareType) {
        List<CostDepartmentProfitVO> list = new ArrayList<>();
        int finalYear = year;
        int finalMonth = month;
        responsibilityList.forEach(i -> {
            reportFormList.forEach(j -> {
                CostDepartmentProfitVO costDepartmentProfitVO = new CostDepartmentProfitVO();
                costDepartmentProfitVO.setYear(finalYear);
                costDepartmentProfitVO.setMonth(finalMonth);
                costDepartmentProfitVO.setReportId(j.getId());
                costDepartmentProfitVO.setReportNum(j.getNum());
                costDepartmentProfitVO.setCalcType(j.getCalcType());
                costDepartmentProfitVO.setReportName(j.getReportName());
                costDepartmentProfitVO.setCalcFormula(j.getCalcFormula());
                costDepartmentProfitVO.setReportParentId(j.getParentId());
                costDepartmentProfitVO.setResponsibilityCode(i.getResponsibilityCode());
                costDepartmentProfitVO.setResponsibilityName(i.getResponsibilityName());
                costDepartmentProfitVO.setCostType(NumberConstant.ONE);
                costDepartmentProfitVO.setIncomeType(NumberConstant.ONE);
                costDepartmentProfitVO.setHospId(hospId);
                costDepartmentProfitVO.setShareType(shareType);
                costDepartmentProfitVO.setType(j.getCostType());
                costDepartmentProfitVO.setFraction(j.getFraction());
                list.add(costDepartmentProfitVO);
            });
        });
        Map<Long, List<CostDepartmentProfitVO>> listMap = list.stream().collect(Collectors.groupingBy(CostDepartmentProfitVO::getReportId));
        List<CostDepartmentProfitVO> allList = BeanUtil.convertList(list, CostDepartmentProfitVO.class);
        // 记录每一次计算的钱
        list.forEach(i -> {
            Integer calcType = i.getCalcType();
            if (NumberConstant.ONE.equals(calcType)) {
                // TODO 按照会计科目进行计算
                i.setAmount(setAccountReportData(i, incomeList, allocationQueryReportVOList, reportRelationMap, allList));
            } else if (NumberConstant.TWO.equals(calcType)) {
                // TODO 按照分摊层级进行计算
                i.setAmount(setShareLevelReportData(i, costShareLevelList, reportRelationMap, allocationList, allList));
            } else if (NumberConstant.THREE.equals(calcType)) {
                // TODO 按照小计进行计算
                i.setAmount(setSubtotal(i, costShareLevelList, listMap, list, incomeList, allocationQueryReportVOList, reportRelationMap, allocationList, allList));
            } else if (NumberConstant.FOUR.equals(calcType)) {
                // TODO 按照计算公式进行计算
//                i.setAmount(setCalculation(i, list, costShareLevelList, listMap, incomeList, allocationQueryReportVOList, reportRelationMap, allocationList, allList));
            } else if (NumberConstant.FIVE.equals(calcType)) {
                // TODO  按照责任中心进行计算
                i.setAmount(setResponsibilityCode(i, reportRelationMap, allocationList, allList));
            } else {
                i.setAmount(new BigDecimal("0.000000"));
            }
        });

        //计算占比
        if (CollectionUtils.isEmpty(list)) {
            return list;
        }
        //单独计算计算公式数据
        setCalculationAmount(list);
        //收入
        List<CostDepartmentProfitVO> profitIncomeList = list.stream().filter(f -> f.getType().equals(NumberConstant.ONE)).collect(Collectors.toList());
        List<CostDepartmentProfitVO> profitIncome =
                costPercent(profitIncomeList, "收入");
        //成本
        List<CostDepartmentProfitVO> profitCostList = list.stream().filter(f -> f.getType().equals(NumberConstant.TWO)).collect(Collectors.toList());

        List<CostDepartmentProfitVO> profitCost = costPercent(profitCostList, "成本");

        //不计算项目
        List<CostDepartmentProfitVO> noCompute = list.stream().filter(f -> f.getFraction().equals(NumberConstant.THREE)).collect(Collectors.toList());
        noCompute.forEach(profitVO -> profitVO.setPercent(null));


        if (!CollectionUtils.isEmpty(profitIncome) && !CollectionUtils.isEmpty(profitCost) && !CollectionUtils.isEmpty(noCompute)) {
            profitIncome.addAll(profitCost);
            profitIncome.addAll(noCompute);
            return profitIncome;
        } else if (!CollectionUtils.isEmpty(profitIncome) && !CollectionUtils.isEmpty(noCompute)) {
            profitIncome.addAll(noCompute);
            return profitIncome;
        } else if (!CollectionUtils.isEmpty(profitCost) && !CollectionUtils.isEmpty(noCompute)) {
            profitCost.addAll(noCompute);
            return profitCost;
        } else if (!CollectionUtils.isEmpty(noCompute)) {
            return noCompute;
        } else {
            return list;
        }
    }

    private static void setCalculationAmount(List<CostDepartmentProfitVO> list) {
        Map<String, List<CostDepartmentProfitVO>> collect = list.stream().collect(Collectors.groupingBy(CostDepartmentProfitVO::getResponsibilityCode));
        collect.forEach((responsibilityCode, v) -> {
            //            Map<Integer, BigDecimal> dataMap = new HashMap<>();
//            for (CostDepartmentProfitVO costDepartmentProfitVO : v) {
//                if (costDepartmentProfitVO.getAmount() != null) {
//                    dataMap.put(costDepartmentProfitVO.getReportNum(), costDepartmentProfitVO.getAmount());
//                } else {
//                    dataMap.put(costDepartmentProfitVO.getReportNum(), new BigDecimal("0.000000"));
//                }
//            }
            Map<Integer, List<CostDepartmentProfitVO>> collect1 = v.stream().collect(Collectors.groupingBy(CostDepartmentProfitVO::getCalcType));
            //取出所有计算公式数据
            List<CostDepartmentProfitVO> costDepartmentProfitVOS = collect1.get(NumberConstant.FOUR);
            costDepartmentProfitVOS.sort(Comparator.comparing(CostDepartmentProfitVO::getReportNum, Comparator.nullsLast(Integer::compareTo)));

            for (CostDepartmentProfitVO profitVO : costDepartmentProfitVOS) {
                // 获取当前报表的计算方式  [1]+[2]类型/ [1]-[2] [1]*[2] [1]/[2]
                String formula = profitVO.getCalcFormula();
                //找出公式当中所有代码
                String replace = formula.replace("[", "")
                        .replace("]", "")
                        .replace("-", ",")
                        .replace("+", ",")
                        .replace("*", ",")
                        .replace("/", ",");
                ArrayList<String> codeList = CollUtil.newArrayList(replace.split(","));
                Map<Integer, String> codeMap = new ConcurrentHashMap<>();
                for (int j = 0; j < codeList.size(); j++) {
                    codeMap.put(j, codeList.get(j));
                }
                List<String> expressions = ReUtil.findAll("[^0-9]", "+" + formula.replace("[", "")
                                .replace("]", "").trim(), 0)
                        .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
                // 得到预算表达式 得到所有表达式的Map  +  -  相关的
                Map<Integer, String> expressionMap = new ConcurrentHashMap<>();
                for (int k = 0; k < expressions.size(); k++) {
                    expressionMap.put(k, expressions.get(k));
                }
                // 数字的索引和表达式的索引累加计算
                Set<Integer> codeSet = codeMap.keySet();
                List<Integer> codes = new ArrayList<>(codeSet);
                AtomicReference<BigDecimal> totalAmount = new AtomicReference<>(new BigDecimal("0.000000"));
                for (int i = 0; i < codes.size(); i++) {
                    // 编号
                    String code = codeMap.get(i);
                    BigDecimal amount = null;
                    for (CostDepartmentProfitVO costDepartmentProfitVO : v) {
                        if (costDepartmentProfitVO.getReportNum().equals(Integer.valueOf(code))) {
                            amount = costDepartmentProfitVO.getAmount();
                        }
                    }

//                    BigDecimal amount = dataMap.get(Integer.valueOf(code));
                    if (amount == null) {
                        continue;
                    }
//                    BigDecimal amount = new BigDecimal(o.toString());
                    String str = expressionMap.get(i);
                    if (str.equals("+")) {
                        totalAmount.set(totalAmount.get().add(amount));
                    } else if (str.contains("-")) {
                        totalAmount.set(totalAmount.get().subtract(amount));
                    } else if (str.contains("*")) {
                        totalAmount.set(totalAmount.get().multiply(amount));
                    } else if (str.contains("/")) {
                        if (amount.compareTo(BigDecimal.ZERO.setScale(6, RoundingMode.HALF_UP)) == 0) {
                            totalAmount.set(BigDecimal.ZERO);
                            break;
                        } else {
                            totalAmount.set(totalAmount.get().divide(amount, 6, RoundingMode.HALF_UP));
                        }
                    }
                }
                profitVO.setAmount(totalAmount.get());
            }
        });
    }

    private List<CostDepartmentProfitVO> costPercent(List<CostDepartmentProfitVO> profitIncomeList, String type) {
        List<CostDepartmentProfitVO> list = new ArrayList<>();
        Map<String, List<CostDepartmentProfitVO>> responsibilityGroup = profitIncomeList.stream().collect(Collectors.groupingBy(CostDepartmentProfitVO::getResponsibilityCode));
        responsibilityGroup.forEach((k, v) -> {
            Map<Integer, List<CostDepartmentProfitVO>> collect = v.stream().collect(Collectors.groupingBy(CostDepartmentProfitVO::getFraction));
            //分母只有一个
            List<CostDepartmentProfitVO> denominatorList = collect.get(NumberConstant.TWO);
            if (CollectionUtils.isEmpty(denominatorList)) {
                throw new CostException(type + "项目未配置分母，请查证后再计算科室损益");

            }
            if (denominatorList.size() > 1) {
                throw new CostException(type + "收入项目分母大于一个，请查证后再计算科室损益");
            }
            BigDecimal denominator = denominatorList.get(0).getAmount();
            //收入分子
            List<CostDepartmentProfitVO> numeratorList = collect.get(NumberConstant.ONE);
            if (denominator.compareTo(BigDecimal.ZERO) == 0) {
                for (CostDepartmentProfitVO profitVO : numeratorList) {
                    profitVO.setPercent(BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP));
                }
                denominatorList.get(0).setPercent(BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP));

            } else {
                for (CostDepartmentProfitVO profitVO : numeratorList) {
                    profitVO.setPercent(profitVO.getAmount().divide(denominator, 4, RoundingMode.HALF_UP));
                }
                denominatorList.get(0).setPercent(BigDecimal.ONE.setScale(4, RoundingMode.HALF_UP));
            }
            list.add(denominatorList.get(0));
            list.addAll(numeratorList);
        });

        return list;

    }

    /**
     * 科室损益计算导出
     *
     * @param writer
     * @param sheet
     * @param date
     */
    @Override
    public void getDepartmentProfit(ExcelWriter writer, Sheet sheet, String date) {
        Long hospId = UserContext.getHospId();

        //先展示所有责任中心  非汇总中心 收益中心的责任中心
        // 查询所有的节点
        List<Responsibility> responsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda().eq(Responsibility::getHospId, hospId));
        if (CollUtil.isEmpty(responsibilityList)) {
            throw new CostException(500, "责任中心不存在");
        }
        // 设置表头
        Map<Long, List<Responsibility>> responsibilityMap = responsibilityList.stream().collect(Collectors.groupingBy(Responsibility::getId));
        List<Responsibility> responsibilities = responsibilityList.stream().filter(i -> NumberConstant.TWO.equals(i.getIsGatherCenter()) && NumberConstant.ONE.equals(i.getResponsibilityType())).collect(Collectors.toList());
        Map<Long, List<Responsibility>> responsibilityParentMap = responsibilities.stream().collect(Collectors.groupingBy(Responsibility::getParentId));
        Set<Long> keySet = responsibilityParentMap.keySet();
        int column = 2;
        for (Long parentId : keySet) {
            // 同一父节点的叶子节点数据
            List<Responsibility> list = responsibilityParentMap.get(parentId);
            for (int i = 0; i < list.size(); i++) {
                String responsibilityName1 = list.get(i).getResponsibilityName();
                // 父层级责任中心名称
                List<Responsibility> responsibilityList1 = responsibilityMap.get(list.get(i).getParentId());
                if (CollUtil.isEmpty(responsibilityList1)) {
                    writer.writeCellValue(column, 0, null);
                } else {
                    // 父层级责任中心名称
                    String responsibilityName = responsibilityList1.get(0).getResponsibilityName();
                    // 子层级责任中心名称
                    writer.writeCellValue(column, 0, responsibilityName);
                }
                writer.writeCellValue(column, 1, responsibilityName1);
                column++;
            }
        }
        writer.merge(1, 1, 0, 1, "项目", false);
        DateTime dateTime = DateUtil.parse(date);
        int year = DateUtil.year(dateTime);
        int month = DateUtil.month(dateTime) + 1;

        // 设置列
        List<CostDepartmentProfit> departmentProfits = this.list(new QueryWrapper<CostDepartmentProfit>().lambda()
                .eq(CostDepartmentProfit::getHospId, hospId)
                .eq(CostDepartmentProfit::getYear, year).eq(CostDepartmentProfit::getMonth, month).eq(CostDepartmentProfit::getShareType, 0));
        // 用来筛选金额
        Map<String, CostDepartmentProfit> profitMap = departmentProfits.stream().filter(i -> i.getReportParentId() != 0L).collect(Collectors.toMap(k -> k.getReportName() + "cost" + k.getResponsibilityName(), synOne -> synOne));
        // 报表的父层级报表
        Map<Long, List<CostDepartmentProfit>> departmentParentReportMap = departmentProfits.stream().filter(i -> i.getReportParentId() == 0L)
                .collect(Collectors.groupingBy(CostDepartmentProfit::getReportId)).entrySet().stream()
                .sorted(Map.Entry.comparingByKey()).collect(
                        Collectors.toMap(
                                Map.Entry::getKey,
                                Map.Entry::getValue,
                                (oldVal, newVal) -> oldVal,
                                LinkedHashMap::new
                        )
                );
        // 不是父节点的所有叶子节点
        Map<Long, List<CostDepartmentProfit>> listParentMap = departmentProfits.stream().filter(i -> i.getReportParentId() != 0L).collect(Collectors.groupingBy(CostDepartmentProfit::getReportParentId));
        Set<Long> ids = departmentParentReportMap.keySet();
        // 默认是在第二行开始的

        int row = 2;
        int columnNum = 0;
        for (Long id : ids) {
            String reportParentName = departmentParentReportMap.get(id).get(0).getReportName();
            List<CostDepartmentProfit> profitList = listParentMap.get(id);
            Map<Integer, List<CostDepartmentProfit>> linkedHashMap = profitList.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getReportNum)).entrySet().stream()
                    .sorted(Map.Entry.comparingByKey()).collect(
                            Collectors.toMap(
                                    Map.Entry::getKey,
                                    Map.Entry::getValue,
                                    (oldVal, newVal) -> oldVal,
                                    LinkedHashMap::new
                            ));
            Set<Integer> reportNums = linkedHashMap.keySet();
            for (Integer reportNum : reportNums) {
                // 这一行要显示的记录
                List<CostDepartmentProfit> costDepartmentProfits = linkedHashMap.get(reportNum);
                // 子层级扥报表名称
                String reportName = costDepartmentProfits.get(0).getReportName();
                for (int i = 0; i < costDepartmentProfits.size(); i++) {
                    // 添加项目名称
                    columnNum++;
                    writer.writeCellValue(0, row, reportParentName);
                    writer.writeCellValue(1, row, reportName);
                    for (int j = 0; j < column - 2; j++) {
                        // TODO 设置添加具体金额
                        // 获取表格对应的字段的值
                        String responsibilityTopName = sheet.getRow(1).getCell(j + 2).getStringCellValue();
                        String reportTopName = sheet.getRow(row).getCell(1).getStringCellValue();
                        BigDecimal amount = profitMap.get(reportTopName + "cost" + responsibilityTopName).getAmount();
                        writer.writeCellValue(j + 2, row, amount);

                    }
                }
                row++;
            }
        }
        // TODO 合并留在最后
        int cc = 2;
        // 合并行
        for (int m = 2; m < column - 1; m++) {
            String cellValue1 = sheet.getRow(0).getCell(m).getStringCellValue();
            String cellValue2 = sheet.getRow(0).getCell(m + 1).getStringCellValue();
            if (!cellValue1.equals(cellValue2)) {
                if (cc != m) {
                    writer.merge(0, 0, cc, m, cellValue1, false);
                } else {
                    writer.writeCellValue(cc, 0, cellValue1);
                }

                cc = m + 1;
            } else if (m == column - 2) {
                writer.merge(0, 0, cc, m + 1, sheet.getRow(0).getCell(m + 1).getStringCellValue(), false);
            }
        }
        // 合并列
        int jj = 2;


        for (int i = 2; i < row - 1; i++) {
            String cellValue1 = sheet.getRow(i).getCell(0).getStringCellValue();
            String cellValue2 = sheet.getRow(i + 1).getCell(0).getStringCellValue();
            if (!cellValue1.equals(cellValue2)) {
                if (jj != i) {
                    writer.merge(jj, i, 0, 0, cellValue1, false);
                } else {
                    writer.writeCellValue(0, jj, cellValue1);
                }
                jj = i + 1;
            } else if (i == row - 2) {
                writer.merge(jj, i + 1, 0, 0, cellValue1, false);
            }
        }
        // 设置列宽
        for (int i = 0; i < 50; i++) {
            // 调整每一列宽度
            sheet.autoSizeColumn((short) i);
            // 解决自动设置列宽中文失效的问题
            sheet.setColumnWidth(i, sheet.getColumnWidth(i) * 14 / 10);
        }
    }

    private void getDepartmentProfit(String date, OutputStream outputStream, Integer reportType, String name) throws Exception {

        Long hospId = UserContext.getHospId();
        DateTime dateTime = DateUtil.parse(date);
        int year = DateUtil.year(dateTime);
        int month = DateUtil.month(dateTime) + 1;
        // 查询所有的节点
        List<Responsibility> responsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda().eq(Responsibility::getHospId, hospId));
        if (CollUtil.isEmpty(responsibilityList)) {
            throw new CostException(500, "责任中心不存在");
        }
        Map<String, Long> responseCodeParentIdMap = responsibilityList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getParentId, (a, b) -> b));
//        Map<String,Long> responseCodeIdMap = responsibilityList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getId, (a, b) -> b));

        Map<Long, Responsibility> responsibilityIdMap = responsibilityList.stream().collect(Collectors.toMap(Responsibility::getId, responsibility -> responsibility, (a, b) -> b));

//        Map<Long, List<Responsibility>> responsibilityMap = responsibilityList.stream().collect(Collectors.groupingBy(Responsibility::getId));
//        List<Responsibility> responsibilities = responsibilityList.stream().filter(i -> NumberConstant.TWO.equals(i.getIsGatherCenter()) && NumberConstant.ONE.equals(i.getResponsibilityType())).collect(Collectors.toList());
//        Map<Long, List<Responsibility>> responsibilityParentMap = responsibilities.stream().collect(Collectors.groupingBy(Responsibility::getParentId));
//

        // 表头
        List<CostDepartmentProfit> departmentProfits = this.list(new QueryWrapper<CostDepartmentProfit>().lambda()
                .eq(CostDepartmentProfit::getHospId, hospId)
                .eq(CostDepartmentProfit::getYear, year).eq(CostDepartmentProfit::getMonth, month)
                .eq(CostDepartmentProfit::getShareType, reportType));
        if (CollectionUtils.isEmpty(departmentProfits)) {
            throw new CostException(500, name + "未进行科室损益计算");
        }
        for (CostDepartmentProfit departmentProfit : departmentProfits) {
            Long aLong = responseCodeParentIdMap.get(departmentProfit.getResponsibilityCode());
            if (aLong != null) {
                if (aLong.equals(NumberConstant.ZERO_L)) {
//                    Long aLong1 = responseCodeIdMap.get(departmentProfit.getResponsibilityCode());
                    departmentProfit.setParentResponsibilityCode(departmentProfit.getResponsibilityCode());
                    departmentProfit.setParentResponsibilityName(departmentProfit.getResponsibilityName());
                } else {
                    Responsibility responsibility = responsibilityIdMap.get(aLong);
                    if (Objects.nonNull(responsibility)) {
                        departmentProfit.setParentResponsibilityCode(responsibility.getResponsibilityCode());
                        departmentProfit.setParentResponsibilityName(responsibility.getResponsibilityName());
                    }
                }

            }
        }
        //损益表设置
        List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
                .eq(ReportForm::getHospId, hospId)
                .eq(ReportForm::getReportType, reportType));
        if (CollUtil.isEmpty(reportFormList)) {
            throw new CostException(500, "损益表未找到");
        }
        Map<Long, List<ReportForm>> collect = reportFormList.stream().collect(Collectors.groupingBy(ReportForm::getParentId));

        Map<String, List<ColEntity>> heads = new HashMap<>();// 最终导出的多个sheet的表头
        Map<String, List<Map<String, String>>> datas = new HashMap<>();// 最终导出的多个sheet的内容
        Map<String, Integer> types = new HashMap<>();
        Map<String, List<Integer>> mergeindexs = new HashMap<>();// 最终导出的每个sheet的需要纵向合并的单元格列号


        //第一层
        List<ReportForm> firstTitle = collect.get(NumberConstant.ZERO_L);
        List<TitleEntity> titleList = new ArrayList<>();
        titleList.add(new TitleEntity("0", null, name, false, NumberConstant.ZERO));

        //添加默认三列责任中心
        setDefaultColumn(titleList);
        for (ReportForm reportForm : firstTitle) {
            TitleEntity entity = new TitleEntity();
            entity.setId(String.valueOf(reportForm.getId()));
            entity.setPid(String.valueOf(reportForm.getParentId()));
            entity.setContent(reportForm.getReportName());
            entity.setFieldName(String.valueOf(reportForm.getNum()));
            entity.setWidth(20);
            entity.setSort(reportForm.getSort());
            boolean child = getChild(titleList, reportForm, collect);
            entity.setLast(child);
            titleList.add(entity);
        }
        titleList.sort(Comparator.comparing(TitleEntity::getSort));

//        List<CostDepartmentProfit> costDepartmentProfitsDoctor = departmentProfits.stream().filter(f -> f.getShareType().equals(NumberConstant.ONE)).collect(Collectors.toList());
//        List<CostDepartmentProfit> costDepartmentProfits = departmentProfits.stream().filter(f -> f.getShareType().equals(NumberConstant.TWO)).collect(Collectors.toList());

        //行
        Map<String, List<CostDepartmentProfit>> doctorParentMap = departmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getParentResponsibilityCode));
//        Map<String, List<CostDepartmentProfit>> yiParentMap = costDepartmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getParentResponsibilityCode));


        //列
        List<TitleEntity> titleEntities = titleList.stream().filter(TitleEntity::isLast).collect(Collectors.toList());
        List<Map<String, String>> rowList = new ArrayList<>();
//        List<Map<String, String>> rowList1 = new ArrayList<>();

        setRowList(doctorParentMap, titleEntities, rowList);
//        setRowList(yiParentMap, titleEntities, rowList1);


        ExcelPoiUtil excelTool = new ExcelPoiUtil(name);
        Map<String, String> param = ImmutableMap.<String, String>builder().put("id", "id").put("pid", "pid")
                .put("content", "content").put("fieldName", "fieldName").put("width", "width").build();
        List<ColEntity> titleData = excelTool.colEntityTransformer(titleList, param, "0");
        Map<String, List<Integer>> autoRowHeights = new HashMap<>();

        heads.put(name, titleData);// 每个sheet的表头，sheet名称为key
        datas.put(name, rowList);// 每个sheet的内容，sheet名称为key
        types.put(name, 0);// 每个sheet的样式类型，sheet名称为key
        mergeindexs.put(name, Arrays.asList(0, 1));// 每个sheet的默认行高，sheet名称为key
        autoRowHeights.put(name, Arrays.asList(1, 2, 3, 4, 5));

//        heads.put("科室损益-医技", titleData);// 每个sheet的表头，sheet名称为key
//        datas.put("科室损益-医技", rowList1);// 每个sheet的内容，sheet名称为key
//        types.put("科室损益-医技", 0);// 每个sheet的样式类型，sheet名称为key
//        mergeindexs.put("科室损益-医技", Arrays.asList(0, 1));// 每个sheet的默认行高，sheet名称为key
//        autoRowHeights.put("科室损益-医技", Arrays.asList(1, 2, 3, 4, 5));


        // 多个sheet导出
        HSSFWorkbook workbook = excelTool.exportWorkbook(heads, datas, types, autoRowHeights, mergeindexs);
//        excelTool.save(workbook, "D:\\科室损益.xls");
        workbook.write(outputStream);
        workbook.close();

    }

    private static void setRowList(Map<String, List<CostDepartmentProfit>> doctorParentMap, List<TitleEntity> titleEntities,
                                   List<Map<String, String>> rowList) {
        DecimalFormat df = new DecimalFormat("0.00%");
        doctorParentMap.forEach((k, v) -> {
            Map<String, List<CostDepartmentProfit>> listMap = v.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getResponsibilityCode));
            listMap.forEach((k1, v1) -> {
                Map<String, CostDepartmentProfit> map = v1.stream().collect(Collectors.toMap(costDepartmentProfit -> String.valueOf(costDepartmentProfit.getReportNum()), costDepartmentProfit -> costDepartmentProfit, (a, b) -> b));
                for (int i = 0; i < 2; i++) {
                    Map<String, String> m = new HashMap<String, String>();
                    for (TitleEntity titleEntity : titleEntities) {

                        if (titleEntity.getId().equals("parentResponsibility")) {
                            m.put("parent", v1.get(0).getParentResponsibilityName());
                        } else if (titleEntity.getId().equals("childResponsibility")) {
                            m.put("child", v1.get(0).getResponsibilityName());
                        } else if (titleEntity.getId().equals("item")) {
                            if (i == 0) {
                                m.put("itemType", "金额");
                            } else {
                                m.put("itemType", "占比");
                            }
                        } else {
                            CostDepartmentProfit profit = map.get(titleEntity.getFieldName());
                            if (Objects.isNull(profit)) {
                                m.put(titleEntity.getFieldName(), "");
                            } else {
                                if (i == 0) {
                                    m.put(titleEntity.getFieldName(), profit.getAmount().setScale(2, RoundingMode.HALF_UP).toString());
                                } else {
                                    if (profit.getPercent() != null) {
                                        m.put(titleEntity.getFieldName(), df.format(profit.getPercent()));
                                    } else {
                                        m.put(titleEntity.getFieldName(), "");
                                    }
                                }
                            }

                        }
                    }
                    rowList.add(m);
                }
            });

        });

    }

    private void setDefaultColumn(List<TitleEntity> titleList) {
        TitleEntity parentResponsibility = new TitleEntity();
        parentResponsibility.setId("parentResponsibility");
        parentResponsibility.setPid("0");
        parentResponsibility.setContent("");
        parentResponsibility.setFieldName("parent");
        parentResponsibility.setWidth(15);
        parentResponsibility.setSort(NumberConstant.ZERO);
        parentResponsibility.setLast(true);
        titleList.add(parentResponsibility);


        TitleEntity childResponsibility = new TitleEntity();
        childResponsibility.setId("childResponsibility");
        childResponsibility.setPid("0");
        childResponsibility.setContent("");
        childResponsibility.setFieldName("child");
        childResponsibility.setWidth(15);
        childResponsibility.setSort(NumberConstant.ZERO);
        childResponsibility.setLast(true);
        titleList.add(childResponsibility);
        TitleEntity item = new TitleEntity();
        item.setId("item");
        item.setPid("0");
        item.setContent("");
        item.setFieldName("itemType");
        item.setWidth(10);
        item.setSort(NumberConstant.ZERO);
        item.setLast(true);
        titleList.add(item);

    }

    private boolean getChild(List<TitleEntity> titleList, ReportForm reportForm, Map<Long, List<ReportForm>> collect) {
        List<ReportForm> forms = collect.get(reportForm.getId());
        if (!CollectionUtils.isEmpty(forms)) {
            for (ReportForm form : forms) {
                TitleEntity entity = new TitleEntity();
                entity.setId(String.valueOf(form.getId()));
                entity.setPid(String.valueOf(form.getParentId()));
                entity.setContent(form.getReportName());
                entity.setFieldName(String.valueOf(form.getNum()));
                entity.setWidth(15);
                entity.setSort(form.getSort());
                boolean last = getChild(titleList, form, collect);
                entity.setLast(last);
                titleList.add(entity);
            }
            return false;
        } else {
            return true;
        }

    }

    private boolean getChild(List<TitleEntity> titleList, String parentResponsibilityCode,
                             Map<String, List<ResponsibilityVo>> collect, Map<String, Long> responseCodeIdMap, String pid) {
        List<ResponsibilityVo> forms = collect.get(parentResponsibilityCode);
        if (!CollectionUtils.isEmpty(forms)) {
            for (ResponsibilityVo form : forms) {
                TitleEntity entity = new TitleEntity();
                entity.setPid(pid);
                entity.setContent(form.getResponsibilityName());
                entity.setFieldName(form.getResponsibilityName());
                entity.setWidth(10);
                entity.setSort(form.getSort());
                if (form.getResponsibilityCode().equals(parentResponsibilityCode)) {
                    entity.setId(responseCodeIdMap.get(form.getResponsibilityCode()) + "child");
                    entity.setLast(false);
                    titleList.add(entity);
                    //添加固定两列金额 占比
                    TitleEntity amountEntity = new TitleEntity();
                    amountEntity.setId(parentResponsibilityCode + "|" + AMOUNT_FIELD);
                    amountEntity.setPid(responseCodeIdMap.get(form.getResponsibilityCode()) + "child");
                    amountEntity.setContent("金额");
                    amountEntity.setFieldName(parentResponsibilityCode + "|" + AMOUNT_FIELD);
                    amountEntity.setWidth(15);
                    amountEntity.setSort(2);
                    amountEntity.setLast(true);
                    titleList.add(amountEntity);
                    TitleEntity percentEntity = new TitleEntity();
                    percentEntity.setId(parentResponsibilityCode + "|" + PERCENT_FIELD);
                    percentEntity.setPid(responseCodeIdMap.get(form.getResponsibilityCode()) + "child");
                    percentEntity.setContent("占比");
                    percentEntity.setFieldName(parentResponsibilityCode + "|" + PERCENT_FIELD);
                    percentEntity.setWidth(10);
                    percentEntity.setSort(2);
                    percentEntity.setLast(true);
                    titleList.add(percentEntity);
                } else {
                    entity.setId(String.valueOf(responseCodeIdMap.get(form.getResponsibilityCode())));

                    boolean last = getChild(titleList, form.getResponsibilityCode(), collect, responseCodeIdMap, String.valueOf(responseCodeIdMap.get(form.getResponsibilityCode())));
                    entity.setLast(last);
                    titleList.add(entity);
                }

            }
        } else {
            //添加固定两列金额 占比
            TitleEntity amountEntity = new TitleEntity();
            amountEntity.setId(parentResponsibilityCode + "|" + AMOUNT_FIELD);
            amountEntity.setPid(pid);
            amountEntity.setContent("金额");
            amountEntity.setFieldName(parentResponsibilityCode + "|" + AMOUNT_FIELD);
            amountEntity.setWidth(15);
            amountEntity.setSort(2);
            amountEntity.setLast(true);
            titleList.add(amountEntity);
            TitleEntity percentEntity = new TitleEntity();
            percentEntity.setId(parentResponsibilityCode + "|" + PERCENT_FIELD);
            percentEntity.setPid(pid);
            percentEntity.setContent("占比");
            percentEntity.setFieldName(parentResponsibilityCode + "|" + PERCENT_FIELD);
            percentEntity.setWidth(10);
            percentEntity.setSort(2);
            percentEntity.setLast(true);
            titleList.add(percentEntity);
        }
        return false;

    }

    private List<ExcelExportEntity> getEntityList(ReportForm reportForm, Map<Long, List<ReportForm>> collect) {
        List<ExcelExportEntity> list = new ArrayList<>();
        List<ReportForm> forms = collect.get(reportForm.getId());
        if (!CollectionUtils.isEmpty(forms)) {
            for (ReportForm form : forms) {
                ExcelExportEntity entity = new ExcelExportEntity();
                entity.setName(form.getReportName());
                entity.setKey(form.getNum());
                entity.setOrderNum(form.getSort());
                entity.setList(getEntityList(form, collect));
                list.add(entity);
            }

        }
        return list;
    }


    /**
     * 科室损益计算导出
     *
     * @param date
     * @param hospId
     * @param reportType
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void getDepartProfitReport(String date, Long hospId, Integer reportType) throws Exception {
        DateTime dateTime = DateUtil.parse(date);
        int year = DateUtil.year(dateTime);
        int month = DateUtil.month(dateTime) + 1;
        int day = DateUtil.dayOfMonth(dateTime);

        DictDataVo dict = centerService.getDict(PROFIT_REPORT_TYPE);
        if (Objects.isNull(dict)) {
            throw new CostException("未找到损益报表类型字典");
        }
        List<DictDataVo> dataVoList = dict.getDataVoList();
        if (CollectionUtils.isEmpty(dataVoList)) {
            throw new CostException("未找到损益报表类型字典");
        }
//        Map<String, DictDataVo> dictMap = dataVoList.stream().collect(Collectors.toMap(DictDataVo::getCode, vo -> vo, (a, b) -> b));
        //去除全院损益字典
        List<DictDataVo> collect = dataVoList.stream().filter(f -> f.getValue().equals(NumberConstant.ONE_S)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(collect)) {
            throw new CostException("未找到科室损益报表类型字典");
        }
        for (DictDataVo vo : collect) {

            Integer reportDictType = Integer.valueOf(vo.getCode());
//
            String time = DateUtil.format(DateUtil.date(), "yyyy年MM月dd日HH时mm分ss秒");
//
            FileItemFactory factory = new DiskFileItemFactory(5242880, null);
//
            FileItem fileItem = factory.createItem("file", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8", true, vo.getName() + time + ".xlsx");
////            try {
            OutputStream outputStream = fileItem.getOutputStream();
//                getDepartmentProfit(date, outputStream, reportDictType,vo.getName());
            exportDepartmentProfit(date, outputStream, reportDictType, vo.getName());


//            } catch (Exception e) {
//                throw new RuntimeException(e);
//            }
            MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
            String file = uploadFile(multipartFile);
            FileRecord fileRecord = new FileRecord();
            fileRecord.setFileName(vo.getName() + time + ".xlsx")
                    .setFileSource(reportType)
                    .setFileType(vo.getName())
                    .setFileUrl(file)
                    .setHospId(hospId)
                    .setDateYear(year).setDateMonth(month)
                    .setCreateTime(System.currentTimeMillis());
            fileRecordService.save(fileRecord);
            fileItem.delete();
        }
    }

//        public void getDepartProfitReport(String date, Long hospId, Integer reportType) throws Exception {
//        DateTime dateTime = DateUtil.parse(date);
//        int year = DateUtil.year(dateTime);
//        int month = DateUtil.month(dateTime) + 1;
//        int day = DateUtil.dayOfMonth(dateTime);
//
//
//            String time = DateUtil.format(DateUtil.date(), "yyyy年MM月dd日HH时mm分ss秒");
//            FileItemFactory factory = new DiskFileItemFactory(5242880, null);
//            FileItem fileItem = factory.createItem("file", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8", true, "测试临床" + time + ".xls");
//            OutputStream  outputStream = fileItem.getOutputStream();
//
//            handleDepartmentProfit(date, outputStream,8,"测试临床");
//
//    }


    private void getLastDefaultHeader(List<TitleEntity> titleList, String responsibilityId) {
        TitleEntity amountEntity = new TitleEntity();
        amountEntity.setId(NumberConstant.ONE_S);
        amountEntity.setPid(responsibilityId);
        amountEntity.setContent(AMOUNT);
        amountEntity.setFieldName(AMOUNT);
        amountEntity.setWidth(20);
        amountEntity.setLast(true);
        titleList.add(amountEntity);
        TitleEntity percentEntity = new TitleEntity();
        percentEntity.setId(NumberConstant.TWO_S);
        percentEntity.setPid(responsibilityId);
        percentEntity.setContent(PERCENT);
        percentEntity.setFieldName(PERCENT);
        percentEntity.setWidth(20);
        percentEntity.setLast(true);
        titleList.add(percentEntity);
    }

    public String uploadFile(MultipartFile file) {
        Long hospId = UserContext.getCurrentLoginHospId();
        String fileName = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf(".")) + System.currentTimeMillis() + ".xls";
        DateTime date = DateUtil.date();
        int month = DateUtil.month(date) + 1;
        int year = DateUtil.year(date);
        int day = DateUtil.dayOfMonth(date);
        String fileUrl = "";
        try {
//            file.transferTo(new File(localFilePath));
//            String format = DateUtil.format(date, DatePattern.PURE_DATETIME_PATTERN);

            String dataDirectory = minioConfig.getBucketName();
            String uploadFileName = "departReport" + "/" + hospId + "/" + year + "/" + month + "/" + day + "/" + fileName;


            InputStream inputStream = file.getInputStream();

            minioFileUtil.putObject(dataDirectory, uploadFileName, inputStream);
            fileUrl = minioFileUtil.getObjectUrl(dataDirectory, uploadFileName);

        } catch (IOException e) {
            log.error("【文件上传至服务器】失败，绝对路径：{}", e.getMessage());
            throw new CostException(ErrorCodeEnum.FILE_UPLOAD_ERROR);
        }
        return fileUrl;
    }


    /**
     * 删除科室损益数据
     *
     * @param idList 科室损益的Id的集合
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void deleteByIds(List<Long> idList) {
        this.removeByIds(idList);
    }

    @Override
    public void computeProfit(String computeDate, Long hospId, String reportType) {
        //需要用代码计算时
        if(IsNeedCalc(reportType)){
            String parameterValue = centerService.getParameterValue(ParameterConstant.ALLOCATION_TYPE);
            if (NumberConstant.ONE_S.equals(parameterValue)) {
                //按责任中心分摊的科室损益计算
                computeProfitAction(computeDate, hospId, reportType);
            }else if (NumberConstant.TWO_S.equals(parameterValue)) {
                //按会计科目分摊的科室损益计算
                calcDeptProfit(computeDate, hospId, reportType);
            }
            //计算同环比
            handleSpecificMonthsCalculation(hospId, computeDate, reportType);
        }
        execDeptProfitSql(computeDate, reportType);
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void computeProfitAction(String computeDate, Long hospId, String reportType) {
//        DateTime parse = DateUtil.parse(computeDate);
//        int year = DateUtil.year(parse);
//        int month = DateUtil.month(parse) + 1;
        Long userId = UserContext.getCurrentUser().getId();
        Integer year = ComputeDateUtils.getComputeYear(computeDate);
        Integer month = ComputeDateUtils.getComputeMonth(computeDate);
        // 先查询指定条件的报表数据  查询损益表的数据
        List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
                .eq(ReportForm::getHospId, hospId)
                .eq(ReportForm::getReportType, reportType));
        if (CollUtil.isEmpty(reportFormList)) {
            throw new CostException(500, "损益表未找到");
        }
        // 遍历报表数据根据报表数据计算方式进行计算


        //这里拆分成两个 原有的最后一层 以及 参数医技
        DictDataVo dataVo = getDictDataVo(reportType);
        Long id = Long.valueOf(dataVo.getExpandOne());
        // 查询最后一个层级的责任中心
        List<CostShareLevel> costShareLevelList = costShareLevelService.list(new QueryWrapper<CostShareLevel>().lambda()
                .eq(CostShareLevel::getHospId, hospId).orderByDesc(CostShareLevel::getLeverSort));
        if (CollUtil.isEmpty(costShareLevelList)) {
            throw new CostException(500, "分摊层级未设置");
        }
//        // TODO 可能多个
//        Long id = costShareLevelList.get(0).getId();
        // 查询责任中心里面是这个层级的所有的收益中心
//        List<Responsibility> responsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
//                .eq(Responsibility::getHospId, hospId).eq(Responsibility::getResponsibilityType, NumberConstant.ONE).eq(Responsibility::getShareId, id));

        List<Responsibility> responsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
                .eq(Responsibility::getHospId, hospId).eq(Responsibility::getShareId, id));


        // 查询责任中心里面是医技分摊层级的
//        List<Responsibility> medicalTechniquesResponsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
//                .eq(Responsibility::getHospId, hospId).eq(Responsibility::getShareId, value));
        // 归集后
        List<IncomeCollection> incomeList = incomeCollectionService.list(new QueryWrapper<IncomeCollection>().lambda()
                .eq(IncomeCollection::getHospId, hospId)
                .eq(year > 0, IncomeCollection::getYear, year).eq(month > 0, IncomeCollection::getMonth, month));
        if (CollUtil.isEmpty(incomeList)) {
            throw new CostException(500, "归集后数据不存在");
        }
        Map<Long, List<ReportRelation>> reportRelationMap = reportRelationService.list(new QueryWrapper<ReportRelation>().lambda().eq(ReportRelation::getHospId, hospId)).stream().collect(Collectors.groupingBy(ReportRelation::getReportId));
        // 分摊后的数据说明是分摊后的数据 这里原有为收益中心数据 同步添加医技分摊后数据
        List<AllocationQuery> allocationQueryList = allocationQueryService.list(new QueryWrapper<AllocationQuery>().lambda().eq(AllocationQuery::getHospId, hospId)
                .eq(year > 0, AllocationQuery::getDateYear, year)
                .eq(month > 0, AllocationQuery::getDateMonth, month));
        if (CollUtil.isEmpty(allocationQueryList)) {
            throw new CostException(500, "分摊后数据不存在");
        }

        // 封装数据
        List<AllocationQueryReportVO> allocationQueryReportVOList = BeanUtil.convertList(allocationQueryList, AllocationQueryReportVO.class);
        allocationQueryReportVOList.forEach(i -> {
            i.setAccountingCodes(Arrays.asList(i.getAccountingCode().split(StrUtil.COMMA)));
            i.setAccountingNames(Arrays.asList(i.getAccountingName().split(StrUtil.COMMA)));
        });

        // 查询分摊的报表数据 后面的计算方式需要使用 小计等需要使用
        List<Allocation> allocationList = allocationService.list(new QueryWrapper<Allocation>().lambda().eq(Allocation::getHospId, hospId)
                .eq(year > 0, Allocation::getDateYear, year).eq(month > 0, Allocation::getDateMonth, month));
        if (CollUtil.isEmpty(allocationList)) {
            throw new CostException(500, "分摊报表数据不存在");
        }

        // 查询所有指定类型的损益表
        // 每个责任中心对应报表都要生成记录
        // 封装需要设置的数据
        List<CostDepartmentProfitVO> list = getCostDepartmentProfitVOS(hospId, year, month, reportFormList, costShareLevelList, responsibilityList, incomeList, reportRelationMap, allocationQueryReportVOList, allocationList, Integer.valueOf(reportType));


        // 删除这个年月的数据
        this.remove(new QueryWrapper<CostDepartmentProfit>().lambda().eq(CostDepartmentProfit::getHospId, hospId)
                .eq(CostDepartmentProfit::getYear, year).eq(CostDepartmentProfit::getMonth, month).eq(CostDepartmentProfit::getShareType, Integer.valueOf(reportType)));
        // 添加数据
        List<CostDepartmentProfit> costDepartmentProfits = BeanUtil.convertList(list, CostDepartmentProfit.class);

        long l = System.currentTimeMillis();
        costDepartmentProfits.forEach(i -> {
            i.setCreateTime(l);
        });

        this.saveBatch(costDepartmentProfits);
        //记录最后一次 损益计算日期
        computeLastProfitDateRepository.saveLastComputeDate(hospId, computeDate,userId);
    }

    /**
     * 处理指定月份及关联月份的计算（当前月、下个月、明年同月）
     *
     * @param hospId      院区ID
     * @param computeDate 日期字符串，格式：YYYY-MM
     * @param shareType   报表类型
     */
    public void handleSpecificMonthsCalculation(Long hospId, String computeDate, String shareType) {
        // 解析输入的年月
        Integer currentYear = ComputeDateUtils.getComputeYear(computeDate);
        Integer currentMonth = ComputeDateUtils.getComputeMonth(computeDate);
        // 计算需要处理的期间信息
        List<PeriodInfoVO> periods = calculateAllRelatedPeriods(currentYear, currentMonth);

        // 获取所有相关的期间数据
        Map<String, List<CostDepartmentProfit>> allDataMap = loadAllPeriodData(hospId, shareType, periods);

        // 对每个期间执行计算
        for (PeriodInfoVO period : periods) {
            String currentKey = buildPeriodKey(period.getYear(), period.getMonth());
            if (allDataMap.containsKey(currentKey) && !CollectionUtils.isEmpty(allDataMap.get(currentKey))) {
                List<CostDepartmentProfit> currentRecords = allDataMap.get(currentKey);
                List<CostDepartmentProfit> prevRecords = getPeriodData(allDataMap, period.getPrevYear(), period.getPrevMonth());
                List<CostDepartmentProfit> lastYearRecords = getPeriodData(allDataMap, period.getLastYear(), period.getLastMonth());

                // 执行批量计算
                calculatePeriodComparisonWithPreloadedData(currentRecords, prevRecords, lastYearRecords);
            }
        }
    }

    /**
     * 构建所有需要处理的期间信息
     */
    private List<PeriodInfoVO> calculateAllRelatedPeriods(int baseYear, int baseMonth) {
        List<PeriodInfoVO> result = new ArrayList<>();

        // 添加当前期间
        result.add(calculatePeriodInfo(baseYear, baseMonth));

        // 下个月
        int nextMonth = baseMonth + 1;
        int nextMonthYear = baseYear;
        if (baseMonth == 12) {
            nextMonth = 1;
            nextMonthYear += 1;
        }
        result.add(calculatePeriodInfo(nextMonthYear, nextMonth));

        // 明年同月
        result.add(calculatePeriodInfo(baseYear + 1, baseMonth));

        return result;
    }

    /**
     * 构建单个期间的信息（当前月、上月、去年同期）
     */
    private PeriodInfoVO calculatePeriodInfo(int year, int month) {
        PeriodInfoVO info = new PeriodInfoVO();

        info.setYear( year);
        info.setMonth( month);

        // 上期
        if (month == 1) {
            info.setPrevYear(year - 1);
            info.setPrevMonth(12);
        } else {
            info.setPrevYear( year);
            info.setPrevMonth(month - 1);
        }

        // 同期
        info.setLastYear(year - 1);
        info.setLastMonth( month);

        return info;
    }

    /**
     * 加载所有相关期间的数据（去重处理）
     */
    private Map<String, List<CostDepartmentProfit>> loadAllPeriodData(Long hospId, String shareType, List<PeriodInfoVO> periods) {
        Set<String> allPeriodKeys = new HashSet<>();

        // 收集所有需要查询的年月组合
        for (PeriodInfoVO period : periods) {
            allPeriodKeys.add(buildPeriodKey(period.getYear(), period.getMonth()));
            allPeriodKeys.add(buildPeriodKey(period.getPrevYear(), period.getPrevMonth()));
            allPeriodKeys.add(buildPeriodKey(period.getLastYear(), period.getLastMonth()));
        }

        // 去重后查询
        Map<String, List<CostDepartmentProfit>> result = new HashMap<>();
        Set<String> processedKeys = new HashSet<>(); // 已处理的键集合

        for (String key : allPeriodKeys) {
            if (!processedKeys.contains(key)) {
                int[] ym = parsePeriodKey(key);
                List<CostDepartmentProfit> records = getPeriodRecords(hospId, shareType, ym[0], ym[1]);
                result.put(key, records);
                processedKeys.add(key); // 标记为已处理
            }
        }

        return result;
    }


    /**
     * 获取指定期间的数据
     *
     * @param hospId    院区ID
     * @param shareType 报表类型
     * @param year      年份
     * @param month     月份
     * @return 符合条件的数据列表
     */
    private List<CostDepartmentProfit> getPeriodRecords(Long hospId, String shareType, int year, int month) {
        return this.list(new QueryWrapper<CostDepartmentProfit>().lambda()
                .eq(CostDepartmentProfit::getHospId, hospId)
                .eq(CostDepartmentProfit::getShareType, shareType)
                .eq(CostDepartmentProfit::getYear, year)
                .eq(CostDepartmentProfit::getMonth, month)
                .eq(CostDepartmentProfit::getDeleteTime, 0));
    }

    /**
     * 根据年月获取对应的数据（从内存中查找）
     */
    private List<CostDepartmentProfit> getPeriodData(Map<String, List<CostDepartmentProfit>> dataMap, int year, int month) {
        String key = buildPeriodKey(year, month);
        return dataMap.getOrDefault(key, Collections.emptyList());
    }

    /**
     * 批量计算同环比及同期金额（使用预加载数据）
     */
    public void calculatePeriodComparisonWithPreloadedData(
            List<CostDepartmentProfit> currentRecords,
            List<CostDepartmentProfit> prevRecords,
            List<CostDepartmentProfit> lastYearRecords) {

        if (CollectionUtils.isEmpty(currentRecords)) {
            return;
        }

        // 创建责任码+报表编号到记录的映射
        Map<String, CostDepartmentProfit> prevMap = new HashMap<>();
        for (CostDepartmentProfit record : prevRecords) {
            String key = buildRecordKey(record);
            prevMap.put(key, record);
        }

        Map<String, CostDepartmentProfit> lastYearMap = new HashMap<>();
        for (CostDepartmentProfit record : lastYearRecords) {
            String key = buildRecordKey(record);
            lastYearMap.put(key, record);
        }

        // 批量更新数据
        for (CostDepartmentProfit record : currentRecords) {
            String key = buildRecordKey(record);
            CostDepartmentProfit prevRecord = prevMap.get(key);
            CostDepartmentProfit lastYearRecord = lastYearMap.get(key);

            // 设置上期和同期金额
            record.setPrevPeriodAmount(prevRecord != null ? prevRecord.getAmount() : BigDecimal.ZERO);
            record.setSamePeriodAmount(lastYearRecord != null ? lastYearRecord.getAmount() : BigDecimal.ZERO);

            // 计算环比和同比
            record.setMomRate(calculateProfitRate(record.getAmount().subtract(record.getSamePeriodAmount()), record.getPrevPeriodAmount()));
            record.setYoyRate(calculateProfitRate(record.getAmount().subtract(record.getSamePeriodAmount()), record.getSamePeriodAmount()));
        }

        // 批量更新数据库
        this.updateBatchById(currentRecords);
    }

    /**
     * 构建期间键（用于存储和检索数据）
     */
    private String buildPeriodKey(int year, int month) {
        return year + "_" + month;
    }

    /**
     * 解析期间键为年月数组
     */
    private int[] parsePeriodKey(String key) {
        String[] parts = key.split("_");
        return new int[]{Integer.parseInt(parts[0]), Integer.parseInt(parts[1])};
    }

    /**
     * 构建记录的唯一标识键（责任码 + 报表编号）
     */
    private String buildRecordKey(CostDepartmentProfit record) {
        return record.getResponsibilityCode() + "_" + record.getReportNum();
    }

    /**
     * 安全地计算百分比：避免除零错误
     */
    private BigDecimal calculateProfitRate(BigDecimal current, BigDecimal base) {
        if (base == null || base.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }
        BigDecimal bigDecimal = current.divide(base, 4, RoundingMode.HALF_UP).setScale(4, RoundingMode.HALF_UP);
        return bigDecimal;
    }



    /**
     * 执行科室损益后续脚本
     *
     * @param computeDate
     * @param reportType
     */
    public void execDeptProfitSql(String computeDate, String reportType) {
        Map<String, String> sqlParameter = new HashMap<>();
        sqlParameter.put(SQLParameter.COMPUTE_DATE_CODE, computeDate);
        sqlParameter.put(SQLParameter.REPORT_TYPE_CODE, reportType);
        sqlService.autoExecuteSql(CustomSqlTypeEnum.DEPT_PROFIT_CALC.getCode(), sqlParameter);
    }


    private DictDataVo getDictDataVo(String reportType) {
        DictDataVo dict = centerService.getDict(PROFIT_REPORT_TYPE);
        if (Objects.isNull(dict)) {
            throw new CostException("未找到损益报表类型字典");
        }
        List<DictDataVo> dataVoList = dict.getDataVoList();
        if (CollectionUtils.isEmpty(dataVoList)) {
            throw new CostException("未找到损益报表类型字典");
        }
        Map<String, DictDataVo> dictMap = dataVoList.stream().collect(Collectors.toMap(DictDataVo::getCode, vo -> vo, (a, b) -> b));
        DictDataVo dataVo = dictMap.get(reportType);
        if (Objects.isNull(dataVo)) {
            throw new CostException("未找到损益报表类型为【" + reportType + "】的字典");
        }
        return dataVo;
    }

    /**
     * 计算界面报表样式展示
     *
     * @param computeDate 核算年月
     * @param hospId      医院id
     * @param reportType  报表类型
     * @return
     */
    @Override
    public Object computeProfitReport(String computeDate, Long hospId, String reportType) {

        Integer year = ComputeDateUtils.getComputeYear(computeDate);
        Integer month = ComputeDateUtils.getComputeMonth(computeDate);
        Integer integerReportType = Integer.valueOf(reportType);

        List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
                .eq(ReportForm::getHospId, hospId)
                .eq(ReportForm::getReportType, integerReportType).eq(ReportForm::getHide, NumberConstant.ONE));
        if (CollUtil.isEmpty(reportFormList)) {
            throw new CostException(500, "损益表未找到");
        }
        List<CommonTitleReportVo> commonTitleReportVos = reportFormList.stream().map(reportForm -> {
            CommonTitleReportVo commonTitleReportVo = new CommonTitleReportVo(reportForm.getId(), reportForm.getParentId(), reportForm.getReportName(), reportForm.getSort());
            commonTitleReportVo.setDataType(reportForm.getDataType());
            commonTitleReportVo.setDecimalPlace(reportForm.getDecimalPlace());
            commonTitleReportVo.setPermil(reportForm.getPermil());
            commonTitleReportVo.setFontColor(reportForm.getFontColor());
            return commonTitleReportVo;
        }).collect(Collectors.toList());
//        List<CommonTitleReportVo> commonTitleReportVos = BeanUtil.convertList(reportFormList,CommonTitleReportVo.class);
        Map<Long, List<CommonTitleReportVo>> collect = commonTitleReportVos.stream().collect(Collectors.groupingBy(CommonTitleReportVo::getParentReportId));
        List<CommonTitleReportVo> titleReportVoList = collect.get(NumberConstant.ZERO_L);
        for (CommonTitleReportVo reportVo : titleReportVoList) {
            List<CommonTitleReportVo> childList = collect.get(reportVo.getReportId());
            if (!CollectionUtils.isEmpty(childList)) {
                childList.sort(Comparator.comparing(CommonTitleReportVo::getSort, Comparator.nullsLast(Integer::compareTo)));
                reportVo.setChildTitle(setReportChildren(childList, collect));
            }
        }
        ProfitReportResponse response = new ProfitReportResponse();
        if (!CollectionUtils.isEmpty(titleReportVoList)) {
            titleReportVoList.sort(Comparator.comparing(CommonTitleReportVo::getSort, Comparator.nullsLast(Integer::compareTo)));
        }
        response.setTitle(titleReportVoList);

        List<CostDepartmentProfit> departmentProfits = this.list(new QueryWrapper<CostDepartmentProfit>().lambda()
                .eq(CostDepartmentProfit::getHospId, hospId)
                .eq(CostDepartmentProfit::getYear, year)
                .eq(CostDepartmentProfit::getMonth, month)
                .eq(CostDepartmentProfit::getShareType, integerReportType));
        if (CollectionUtils.isEmpty(departmentProfits)) {
            response.setData(new ArrayList<>());
            return response;
        }

        List<CostDepartmentProfit> filterProfit = new ArrayList<>();

        Map<Long, List<CostDepartmentProfit>> collectGroup = departmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getReportId));
        for (ReportForm reportForm : reportFormList) {
            Integer hide = reportForm.getHide();
            if (hide.equals(NumberConstant.ONE)) {
                List<CostDepartmentProfit> costDepartmentProfits = collectGroup.get(reportForm.getId());
                if (!CollectionUtils.isEmpty(costDepartmentProfits)) {
                    filterProfit.addAll(costDepartmentProfits);
                }
            }
        }


        List<CostProfitVo> costProfitVos = BeanUtil.convertList(filterProfit, CostProfitVo.class);
        Map<String, List<CostProfitVo>> responseGroup = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getResponsibilityCode));
        //取一行数据 作为父类模版
        Set<Map.Entry<String, List<CostProfitVo>>> entrySet = responseGroup.entrySet();
        Map.Entry<String, List<CostProfitVo>> firstEntry = entrySet.iterator().next();
        List<CostProfitVo> parentModel = firstEntry.getValue();
        //备注：所有记算过的数据都是最后一层责任中心，所以按最后一层责任 中心 找出所有上级责任中心后 给模版添加到上层责任中心
        //按报表类型 取字典
        DictDataVo dataVo = getDictDataVo(reportType);
        Long id = Long.valueOf(dataVo.getExpandOne());
        //按字典给护 的 分摊层级id 查找对应报表 的责任中心 找出的是没有父类的
        List<Responsibility> responsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
                .eq(Responsibility::getHospId, hospId)
                .eq(Responsibility::getShareId, id));
        if (CollectionUtils.isEmpty(responsibilityList)) {
            throw new CostException("未找到对应分摊层级责任中心");
        }
        //获取授权的责任中心
        responsibilityList = userResponsibilityRightService.getAuthorizedResponsibility(responsibilityList);
        //获取当前院区所有的责任中心
        List<Responsibility> responsibilityAllList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
                .eq(Responsibility::getHospId, hospId));
        Map<Long, Responsibility> map = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getId, responsibility -> responsibility, (a, b) -> b));
        Map<String, Long> responseCodeParentIdMap = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getParentId, (a, b) -> b));
        Map<String, String> responseNameMap = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getResponsibilityName, (a, b) -> b));


        //通过查询的最下层责任中心 找到其所有父类责任中心
        List<Responsibility> parentResponseList = new ArrayList<>();
        for (Responsibility responsibility : responsibilityList) {
            if (responsibility.getParentId().equals(NumberConstant.ZERO_L)) {
                parentResponseList.add(responsibility);
            } else {
                Responsibility responsibility1 = map.get(responsibility.getParentId());
                if (Objects.nonNull(responsibility1)) {
                    parentResponseList.add(responsibility1);
                    if (!responsibility1.getParentId().equals(NumberConstant.ZERO_L)) {
                        getResponsibilityParent(responsibility1, map, parentResponseList);
                    }
                }
            }

        }
        //去除重复组装数据
        List<Responsibility> parentResponsibility = parentResponseList.stream().distinct().collect(Collectors.toList());
        //找出最外层用于出参循环
        List<Responsibility> responseParent = parentResponsibility.stream().filter(f -> f.getParentId().equals(NumberConstant.ZERO_L)).collect(Collectors.toList());
        //只留下中间责任中心
        parentResponsibility.removeAll(responseParent);

        //最上级添加模版
        List<CostProfitVo> parentReportVos = new ArrayList<>();
        for (Responsibility responsibility : responseParent) {
            List<CostProfitVo> profitVos = BeanUtil.convertList(parentModel, CostProfitVo.class);
            for (CostProfitVo costProfitVo : profitVos) {
                costProfitVo.setResponsibilityCode(responsibility.getResponsibilityCode());
                costProfitVo.setResponsibilityName(responsibility.getResponsibilityName());
                costProfitVo.setSort(responsibility.getSort());
                costProfitVo.setAmount(BigDecimal.ZERO);
                costProfitVo.setPercent(BigDecimal.ZERO);
                parentReportVos.add(costProfitVo);
            }
        }

        //中间责任中心 添加模版 添加父类责任中心
        List<CostProfitVo> middleReportVos = new ArrayList<>();
        for (Responsibility responsibility : parentResponsibility) {
            List<CostProfitVo> profitVos = BeanUtil.convertList(parentModel, CostProfitVo.class);
            Long aLong = responseCodeParentIdMap.get(responsibility.getResponsibilityCode());
            for (CostProfitVo costProfitVo : profitVos) {
                costProfitVo.setResponsibilityCode(responsibility.getResponsibilityCode());
                costProfitVo.setResponsibilityName(responsibility.getResponsibilityName());
                costProfitVo.setSort(responsibility.getSort());
                costProfitVo.setAmount(BigDecimal.ZERO);
                costProfitVo.setPercent(BigDecimal.ZERO);
                if (aLong.equals(NumberConstant.ZERO_L)) {
                    costProfitVo.setParentResponsibilityCode(responsibility.getResponsibilityCode());
                    costProfitVo.setParentResponsibilityName(responsibility.getResponsibilityName());
                } else {
                    Responsibility responsibility1 = map.get(aLong);
                    if (Objects.nonNull(responsibility1)) {
                        costProfitVo.setParentResponsibilityCode(responsibility1.getResponsibilityCode());
                        costProfitVo.setParentResponsibilityName(responsibility1.getResponsibilityName());
                    }
                }
                middleReportVos.add(costProfitVo);
            }
        }
        // 添加父类责任中心
        //已计算过的数据添加上级责任中心
        for (CostProfitVo departmentProfit : costProfitVos) {
            Long aLong = responseCodeParentIdMap.get(departmentProfit.getResponsibilityCode());
            if (aLong != null) {
                if (aLong.equals(NumberConstant.ZERO_L)) {
//                    Long aLong1 = responseCodeIdMap.get(departmentProfit.getResponsibilityCode());
                    departmentProfit.setParentResponsibilityCode(departmentProfit.getResponsibilityCode());
                    departmentProfit.setParentResponsibilityName(departmentProfit.getResponsibilityName());
                } else {
                    Responsibility responsibility = map.get(aLong);
                    if (Objects.nonNull(responsibility)) {
                        departmentProfit.setParentResponsibilityCode(responsibility.getResponsibilityCode());
                        departmentProfit.setParentResponsibilityName(responsibility.getResponsibilityName());
                    }
                }
            }
        }
        //已计算过的 按责任中心-报表id 分组
        Map<String, Map<Long, List<CostProfitVo>>> sumGroup = new HashMap<>();
        //已计算过的 按父类责任中心分组
        Map<String, List<CostProfitVo>> collect1 = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getParentResponsibilityCode));
        if (!CollectionUtils.isEmpty(collect1)) {
            collect1.forEach((k, v) -> {
                Map<Long, List<CostProfitVo>> collect2 = v.stream().collect(Collectors.groupingBy(CostProfitVo::getReportId));
                sumGroup.put(k, collect2);
            });
        }

        //计算所有中间层
        List<CostProfitVo> middleFilterReportVos = new ArrayList<>();
        for (CostProfitVo middleReportVo : middleReportVos) {
            String responsibilityCode = middleReportVo.getResponsibilityCode();
            Map<Long, List<CostProfitVo>> longListMap = sumGroup.get(responsibilityCode);
            if (!CollectionUtils.isEmpty(longListMap)) {
                List<CostProfitVo> profitVos = longListMap.get(middleReportVo.getReportId());
                AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.0000"));
                if (!CollectionUtils.isEmpty(profitVos)) {
                    profitVos.forEach(m -> {
                        sum.updateAndGet(v -> v.add(m.getAmount()));
                    });

                    middleReportVo.setAmount(sum.get());
                }
            } else {
                //未在最下层找到数据的可能还是一个分类 提取出来
                middleFilterReportVos.add(middleReportVo);
            }
        }
        //用于处理多层级中 有两层中间层的数据
        if (!CollectionUtils.isEmpty(middleFilterReportVos)) {
            handleMiddleFilterReport(middleReportVos, middleFilterReportVos);
        }
        Map<String, Map<Long, List<CostProfitVo>>> sumMiddleGroup = new HashMap<>();
        Map<String, List<CostProfitVo>> collect2 = middleReportVos.stream().collect(Collectors.groupingBy(CostProfitVo::getParentResponsibilityCode));
        if (!CollectionUtils.isEmpty(collect2)) {
            collect2.forEach((k, v) -> {
                Map<Long, List<CostProfitVo>> collect3 = v.stream().collect(Collectors.groupingBy(CostProfitVo::getReportId));
                sumMiddleGroup.put(k, collect3);
            });
        }

        // 最上层的需要执行两次分组 两层时取最后一层计算 多层时取 中间层计算合计
        for (CostProfitVo parentReportVo : parentReportVos) {
            String responsibilityCode = parentReportVo.getResponsibilityCode();
            Map<Long, List<CostProfitVo>> longListMap = sumGroup.get(responsibilityCode);
            //在最下层找到的 说明是两层
            if (!CollectionUtils.isEmpty(longListMap)) {
                List<CostProfitVo> profitVos = longListMap.get(parentReportVo.getReportId());
                AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.0000"));
                if (!CollectionUtils.isEmpty(profitVos)) {
                    profitVos.forEach(m -> {
                        sum.updateAndGet(v -> v.add(m.getAmount()));
                    });
                }
                //再找中间层是否存在子类
                Map<Long, List<CostProfitVo>> longListMap1 = sumMiddleGroup.get(responsibilityCode);
                if (!CollectionUtils.isEmpty(longListMap1)) {
                    List<CostProfitVo> profitVos1 = longListMap1.get(parentReportVo.getReportId());
                    if (!CollectionUtils.isEmpty(profitVos1)) {
                        profitVos1.forEach(m -> {
                            sum.updateAndGet(v -> v.add(m.getAmount()));
                        });
                    }
                }
                parentReportVo.setAmount(sum.get());
            } else {
                //未在最下层找到从中间层找进行计算
                Map<Long, List<CostProfitVo>> longListMap1 = sumMiddleGroup.get(responsibilityCode);
                if (!CollectionUtils.isEmpty(longListMap1)) {
                    List<CostProfitVo> profitVos = longListMap1.get(parentReportVo.getReportId());
                    AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.0000"));
                    if (!CollectionUtils.isEmpty(profitVos)) {
                        profitVos.forEach(m -> {
                            sum.updateAndGet(v -> v.add(m.getAmount()));
                        });
                    }
                    parentReportVo.setAmount(sum.get());
                }
            }
        }
        //把最上层 中间层 最下层组装成一个list  进行分组

        //组装数据
        Map<String, List<CostProfitVo>> collect3 = parentReportVos.stream().collect(Collectors.groupingBy(CostProfitVo::getResponsibilityCode));
        List<CostResponsibilityProfitVo> list = new ArrayList<>();
        collect3.forEach((k, v) -> {
            CostResponsibilityProfitVo vo = new CostResponsibilityProfitVo();
//            List<CostProfitVo> costProfitVos1 = collect3.get(s);
            vo.setResponsibilityCode(k);
            vo.setResponsibilityName(responseNameMap.get(k));
            if (!CollectionUtils.isEmpty(v)) {
                vo.setSort(v.get(0).getSort());
                List<CommonDataReportVo> dataReportVos = new ArrayList<>();
                for (CostProfitVo costProfitVo : v) {
                    CommonDataReportVo vo1 = new CommonDataReportVo();
                    vo1.setReportId(costProfitVo.getReportId());
                    vo1.setValue(costProfitVo.getAmount());
                    dataReportVos.add(vo1);
                }
                vo.setProfitList(dataReportVos);
            } else {
                vo.setSort(NumberConstant.ZERO);
                vo.setProfitList(new ArrayList<>());
            }
            list.add(vo);
        });
        middleReportVos.addAll(costProfitVos);
        Map<String, List<CostProfitVo>> collect5 = middleReportVos.stream().collect(Collectors.groupingBy(CostProfitVo::getResponsibilityCode));
        List<CostResponsibilityProfitVo> list1 = new ArrayList<>();
        collect5.forEach((k, v) -> {
            CostResponsibilityProfitVo vo = new CostResponsibilityProfitVo();
            vo.setResponsibilityCode(k);
            vo.setResponsibilityName(responseNameMap.get(k));
            if (!CollectionUtils.isEmpty(v)) {
                vo.setParentResponsibilityCode(v.get(0).getParentResponsibilityCode());
                vo.setSort(v.get(0).getSort());
                List<CommonDataReportVo> dataReportVos = new ArrayList<>();
                for (CostProfitVo costProfitVo : v) {
                    CommonDataReportVo vo1 = new CommonDataReportVo();
                    vo1.setReportId(costProfitVo.getReportId());
                    vo1.setValue(costProfitVo.getAmount());
                    dataReportVos.add(vo1);
                }
                vo.setProfitList(dataReportVos);
            } else {
                vo.setSort(NumberConstant.ZERO);
                vo.setProfitList(new ArrayList<>());
            }
            list1.add(vo);
        });
        Map<String, List<CostResponsibilityProfitVo>> collect4 = list1.stream().collect(Collectors.groupingBy(CostResponsibilityProfitVo::getParentResponsibilityCode));
        for (CostResponsibilityProfitVo vo : list) {
            List<CostResponsibilityProfitVo> list2 = collect4.get(vo.getResponsibilityCode());
            if (!CollectionUtils.isEmpty(list2)) {
                if (!list2.get(0).getResponsibilityCode().equals(vo.getResponsibilityCode())) {
                    vo.setChild(setProfitChildren(list2, collect4));
                }
            }
        }
        //按责任中心序号排序
        costResponsibilityProfitVoSort(list);
        response.setData(list);

        //提取出最上层


        return response;
    }

    private static void handleMiddleFilterReport(List<CostProfitVo> middleReportVos, List<CostProfitVo> middleFilterReportVos) {
        //去除没计算完的
        middleReportVos.removeAll(middleFilterReportVos);
        //说明有没计算完的
        Map<String, Map<Long, List<CostProfitVo>>> sumFilterGroup = new HashMap<>();
        //已计算过的 按父类责任中心分组
        Map<String, List<CostProfitVo>> collect2 = middleReportVos.stream().collect(Collectors.groupingBy(CostProfitVo::getParentResponsibilityCode));
        if (!CollectionUtils.isEmpty(collect2)) {
            collect2.forEach((k, v) -> {
                Map<Long, List<CostProfitVo>> collect3 = v.stream().collect(Collectors.groupingBy(CostProfitVo::getReportId));
                sumFilterGroup.put(k, collect3);
            });
        }
        for (CostProfitVo middleReportVo : middleFilterReportVos) {
            String responsibilityCode = middleReportVo.getResponsibilityCode();
            Map<Long, List<CostProfitVo>> longListMap = sumFilterGroup.get(responsibilityCode);
            if (!CollectionUtils.isEmpty(longListMap)) {
                List<CostProfitVo> profitVos = longListMap.get(middleReportVo.getReportId());
                AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.0000"));
                if (!CollectionUtils.isEmpty(profitVos)) {
                    profitVos.forEach(m -> {
                        sum.updateAndGet(v -> v.add(m.getAmount()));
                    });
                    middleReportVo.setAmount(sum.get());
                }
            }
            //todo:先处理到四层
        }
        //添加回去
        middleReportVos.addAll(middleFilterReportVos);
    }

    private List<CostResponsibilityProfitVo> setProfitChildren(List<CostResponsibilityProfitVo> child, Map<String, List<CostResponsibilityProfitVo>> collect) {
        for (CostResponsibilityProfitVo reportVo : child) {
            if (!CollectionUtils.isEmpty(collect.get(reportVo.getResponsibilityCode()))) {
                reportVo.setChild(setProfitChildren(collect.get(reportVo.getResponsibilityCode()), collect));
            }
        }
        return child;
    }

    private List<CommonTitleReportVo> setReportChildren(List<CommonTitleReportVo> child, Map<Long, List<CommonTitleReportVo>> collect) {
        for (CommonTitleReportVo reportVo : child) {
            if (!CollectionUtils.isEmpty(collect.get(reportVo.getReportId()))) {
                reportVo.setChildTitle(setReportChildren(collect.get(reportVo.getReportId()), collect));
            }
        }
        if (!CollectionUtils.isEmpty(child)) {
            child.sort(Comparator.comparing(CommonTitleReportVo::getSort, Comparator.nullsLast(Integer::compareTo)));
        }
        return child;
    }

    /**
     * 损益计算获取责任中心列表
     *
     * @param reportType         报表类型
     * @param responsibilityName 责任中心名称
     * @return 责任中心列表
     */
    @Override
    public Object getProfitResponsibility(String reportType, String responsibilityName) {
        Long hospId = UserContext.getHospId();
        DictDataVo dataVo = getDictDataVo(reportType);
        Long id = Long.valueOf(dataVo.getExpandOne());
        List<Responsibility> responsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
                .eq(Responsibility::getHospId, hospId)
                .eq(Responsibility::getShareId, id)
                .and(q -> q.eq(Responsibility::getStatus, NumberConstant.ONE).or().eq(Responsibility::getStatus, null))
                .like(StrUtil.isNotBlank(responsibilityName), Responsibility::getResponsibilityName, responsibilityName));
        if (CollectionUtils.isEmpty(responsibilityList)) {
            throw new CostException("未找到对应分摊层级责任中心");
        }
        //获取授权的责任中心
        responsibilityList = userResponsibilityRightService.getAuthorizedResponsibility(responsibilityList);
        List<Responsibility> responsibilityAllList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
                .eq(Responsibility::getHospId, hospId));
        Map<Long, Responsibility> map = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getId, responsibility -> responsibility, (a, b) -> b));
        List<Responsibility> addList = new ArrayList<>();
        for (Responsibility responsibility : responsibilityList) {
            Responsibility responsibility1 = map.get(responsibility.getParentId());
            if (Objects.nonNull(responsibility1)) {
                addList.add(responsibility1);
                if (!responsibility1.getParentId().equals(NumberConstant.ZERO_L)) {
                    getResponsibilityParent(responsibility1, map, addList);
                }
            }
        }
        if (!CollectionUtils.isEmpty(addList)) {
            //去重
            List<Responsibility> collect = addList.stream().distinct().collect(Collectors.toList());
            responsibilityList.addAll(collect);
        }


        Map<Long, List<Responsibility>> collect = responsibilityList.stream().collect(Collectors.groupingBy(Responsibility::getParentId));
        List<Responsibility> responsibilities = collect.get(NumberConstant.ZERO_L);
        collect.remove(NumberConstant.ZERO_L);
        for (Responsibility responsibility : responsibilities) {
            List<Responsibility> responsibilities1 = collect.get(responsibility.getId());
            if (!CollectionUtils.isEmpty(responsibilities1)) {
                responsibility.setChildren(setResponsibilityChildren(responsibilities1, collect));
            }
        }
        responsibilitySort(responsibilities);
        return responsibilities;
    }


    private void getResponsibilityParent(Responsibility responsibility, Map<Long, Responsibility> collect, List<Responsibility> addList) {
        Responsibility responsibility1 = collect.get(responsibility.getParentId());
        if (Objects.nonNull(responsibility1)) {
            addList.add(responsibility1);
            if (!responsibility1.getParentId().equals(NumberConstant.ZERO_L)) {
                getResponsibilityParent(responsibility1, collect, addList);
            }
        }
    }


    private List<Responsibility> setResponsibilityChildren(List<Responsibility> child, Map<Long, List<Responsibility>> collect) {
        for (Responsibility responsibility : child) {
            if (!CollectionUtils.isEmpty(collect.get(responsibility.getId()))) {
                responsibility.setChildren(setResponsibilityChildren(collect.get(responsibility.getId()), collect));
            }
        }
        return child;
    }


    /**
     * @param computeDate
     * @param hospId
     * @param reportType
     * @param responsibilityCode
     * @return
     */
    @Override
    public Object getComputeProfitList(String computeDate, Long hospId, String reportType, String responsibilityCode) {
        Integer year = ComputeDateUtils.getComputeYear(computeDate);
        Integer month = ComputeDateUtils.getComputeMonth(computeDate);
        //取出计算当前月计算过的科室损益
        List<CostDepartmentProfit> departmentProfits = costDepartmentProfitRepository.getCurrentByReportType(year, month, hospId, reportType, responsibilityCode);
        if (CollectionUtils.isEmpty(departmentProfits)) {
            throw new CostException(500, "未进行科室损益计算");
        }
        Integer integerReportType = Integer.valueOf(reportType);
        List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
                .eq(ReportForm::getHospId, hospId)
                .eq(ReportForm::getReportType, integerReportType));
        if (CollUtil.isEmpty(reportFormList)) {
            throw new CostException(500, "损益表未找到");
        }
        List<CostDepartmentProfit> filterProfit = new ArrayList<>();

        Map<Long, List<CostDepartmentProfit>> collect1 = departmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getReportId));
        for (ReportForm reportForm : reportFormList) {
            Integer hide = reportForm.getHide();
            if (hide.equals(NumberConstant.ONE)) {
//                filterProfit.addAll(collect1.get(reportForm.getId()));
                List<CostDepartmentProfit> costDepartmentProfits = collect1.get(reportForm.getId());
                if (!CollectionUtils.isEmpty(costDepartmentProfits)) {
                    filterProfit.addAll(costDepartmentProfits);
                }
            }
        }


        Map<Long, Integer> sortMap = reportFormList.stream().collect(Collectors.toMap(ReportForm::getId, ReportForm::getSort, (a, b) -> b));
        Map<Long, String> descriptionMap = reportFormList.stream().collect(Collectors.toMap(ReportForm::getId, reportForm -> !StringUtils.isEmpty(reportForm.getDescription()) ? reportForm.getDescription() : "", (a, b) -> b));
        Map<Long, List<ReportForm>> reportIdMap = reportFormList.stream().collect(Collectors.groupingBy(ReportForm::getId));

        List<CostProfitVo> costProfitVos = BeanUtil.convertList(filterProfit, CostProfitVo.class);
        costProfitVos.forEach(profitVo -> {
            profitVo.setDescription(descriptionMap.get(profitVo.getReportId()));
            profitVo.setSort(sortMap.get(profitVo.getReportId()));
            List<ReportForm> profitReportFormList = reportIdMap.get(profitVo.getReportId());
            if (!CollectionUtils.isEmpty(profitReportFormList)) {
                profitVo.setDataType(profitReportFormList.get(NumberConstant.ZERO).getDataType());
                profitVo.setDecimalPlace(profitReportFormList.get(NumberConstant.ZERO).getDecimalPlace());
                profitVo.setPermil(profitReportFormList.get(NumberConstant.ZERO).getPermil());
            } else {
                profitVo.setDataType(NumberConstant.ONE);
                profitVo.setDecimalPlace(NumberConstant.TWO);
                profitVo.setPermil(NumberConstant.ONE);
            }
        });
        Map<Long, List<CostProfitVo>> collect = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getReportParentId));
        List<CostProfitVo> costProfitParentVos = collect.get(NumberConstant.ZERO_L);
        collect.remove(NumberConstant.ZERO_L);
        for (CostProfitVo costProfitVo : costProfitParentVos) {
            List<CostProfitVo> costProfitVo1 = collect.get(costProfitVo.getReportId());
            if (!CollectionUtils.isEmpty(costProfitVo1)) {
                costProfitVo.setChildren(setChildren(costProfitVo1, collect));
            }
        }
        if (!CollectionUtils.isEmpty(costProfitParentVos)) {
            costProfitParentVos.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo)));
        }
        return costProfitParentVos;

    }

    @Override
    public Object getLastComputeDate() {
        Long hospId = UserContext.getHospId();
        ComputeLastProfitDate lastComputeDate = computeLastProfitDateRepository.getLastComputeDate(hospId);
        if (Objects.nonNull(lastComputeDate)) {
            return lastComputeDate.getComputeDate();
        }
        int year = DateUtils.getYear(new Date());
        int month = DateUtils.getMonth(new Date()) + 1;
        if (month < 10) {
            return year + "-0" + month;
        } else {
            return year + "-" + month;
        }

    }

    @Override
    public Object getBatchComputeProfitList(String beginComputeDate, String endComputeDate, Long hospId, String reportType, String responsibilityCode) {
        Map<String, List<CostProfitVo>> map = new HashMap<>();
        List<BatchCostProfitResponse> responses = new ArrayList<>();
        if (beginComputeDate.equals(endComputeDate)) {
            Integer year = ComputeDateUtils.getComputeYear(beginComputeDate);
            Integer month = ComputeDateUtils.getComputeMonth(beginComputeDate);
            //取出计算当前月计算过的科室损益
            List<CostDepartmentProfit> departmentProfits = costDepartmentProfitRepository.getCurrentByReportType(year, month, hospId, reportType, responsibilityCode);
            if (CollectionUtils.isEmpty(departmentProfits)) {
                throw new CostException(500, "未进行科室损益计算");
            }
            Integer integerReportType = Integer.valueOf(reportType);
            List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
                    .eq(ReportForm::getHospId, hospId)
                    .eq(ReportForm::getReportType, integerReportType));
            if (CollUtil.isEmpty(reportFormList)) {
                throw new CostException(500, "损益表未找到");
            }
            Map<Long, List<ReportForm>> reportIdMap = reportFormList.stream().collect(Collectors.groupingBy(ReportForm::getId));
            List<CostDepartmentProfit> filterProfit = new ArrayList<>();

            Map<Long, List<CostDepartmentProfit>> collect1 = departmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getReportId));
            for (ReportForm reportForm : reportFormList) {
                Integer hide = reportForm.getHide();
                if (hide.equals(NumberConstant.ONE)) {
//                    filterProfit.addAll(collect1.get(reportForm.getId()));
                    List<CostDepartmentProfit> costDepartmentProfits = collect1.get(reportForm.getId());
                    if (!CollectionUtils.isEmpty(costDepartmentProfits)) {
                        filterProfit.addAll(costDepartmentProfits);
                    }
                }
            }

            Map<Long, Integer> sortMap = reportFormList.stream().collect(Collectors.toMap(ReportForm::getId, ReportForm::getSort, (a, b) -> b));
            Map<Long, String> descriptionMap = reportFormList.stream().collect(Collectors.toMap(ReportForm::getId, reportForm -> !StringUtils.isEmpty(reportForm.getDescription()) ? reportForm.getDescription() : "", (a, b) -> b));

            List<CostProfitVo> costProfitVos = BeanUtil.convertList(filterProfit, CostProfitVo.class);
            costProfitVos.forEach(profitVo -> {
                profitVo.setDescription(descriptionMap.get(profitVo.getReportId()));
                profitVo.setSort(sortMap.get(profitVo.getReportId()));
                List<ReportForm> profitReportFormList = reportIdMap.get(profitVo.getReportId());
                if (!CollectionUtils.isEmpty(profitReportFormList)) {
                    profitVo.setDataType(profitReportFormList.get(NumberConstant.ZERO).getDataType());
                    profitVo.setDecimalPlace(profitReportFormList.get(NumberConstant.ZERO).getDecimalPlace());
                    profitVo.setPermil(profitReportFormList.get(NumberConstant.ZERO).getPermil());
                    profitVo.setFontColor(profitReportFormList.get(NumberConstant.ZERO).getFontColor());
                } else {
                    profitVo.setDataType(NumberConstant.ONE);
                    profitVo.setDecimalPlace(NumberConstant.TWO);
                    profitVo.setPermil(NumberConstant.ONE);
                }
            });
            Map<Long, List<CostProfitVo>> collect = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getReportParentId));
            List<CostProfitVo> costProfitParentVos = collect.get(NumberConstant.ZERO_L);
            collect.remove(NumberConstant.ZERO_L);
            for (CostProfitVo costProfitVo : costProfitParentVos) {
                List<CostProfitVo> costProfitVo1 = collect.get(costProfitVo.getReportId());
                if (!CollectionUtils.isEmpty(costProfitVo1)) {
                    costProfitVo.setChildren(setChildren(costProfitVo1, collect));
                }
            }
            if (!CollectionUtils.isEmpty(costProfitParentVos)) {
                costProfitParentVos.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo)));
            }
            BatchCostProfitResponse response = new BatchCostProfitResponse();
            response.setComputeDate(beginComputeDate);
            response.setProfitVoList(costProfitParentVos);
            response.setAllowDrillDown(true);
            responses.add(response);
            return responses;
        } else {
            Date date = DateUtils.StringToDate(beginComputeDate, DateStyleEnum.YYYY_MM);
            Date endDate = DateUtils.StringToDate(endComputeDate, DateStyleEnum.YYYY_MM);
            if (DateUtils.compareDate(date, endDate)) {
                throw new CostException("开始日期不能大于结束日期");
            }
            List<String> intervalMonthList = DateUtils.getIntervalMonthList(date, endDate);
            List<CostProfitVo> allCostProfitVo=new ArrayList<>();
            if (!CollectionUtils.isEmpty(intervalMonthList)) {
                for (String computeDates : intervalMonthList) {
                    Integer year = ComputeDateUtils.getComputeYear(computeDates);
                    Integer month = ComputeDateUtils.getComputeMonth(computeDates);
                    //取出计算当前月计算过的科室损益
                    List<CostDepartmentProfit> departmentProfits = costDepartmentProfitRepository.getCurrentByReportType(year, month, hospId, reportType, responsibilityCode);
                    if (CollectionUtils.isEmpty(departmentProfits)) {
                        throw new CostException(500, "未进行科室损益计算");
                    }
                    Integer integerReportType = Integer.valueOf(reportType);
                    List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
                            .eq(ReportForm::getHospId, hospId)
                            .eq(ReportForm::getReportType, integerReportType));
                    if (CollUtil.isEmpty(reportFormList)) {
                        throw new CostException(500, "损益表未找到");
                    }
                    Map<Long, List<ReportForm>> reportIdMap = reportFormList.stream().collect(Collectors.groupingBy(ReportForm::getId));
                    List<CostDepartmentProfit> filterProfit = new ArrayList<>();

                    Map<Long, List<CostDepartmentProfit>> collect1 = departmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getReportId));
                    for (ReportForm reportForm : reportFormList) {
                        Integer hide = reportForm.getHide();
                        if (hide.equals(NumberConstant.ONE)) {
//                            filterProfit.addAll(collect1.get(reportForm.getId()));
                            List<CostDepartmentProfit> costDepartmentProfits = collect1.get(reportForm.getId());
                            if (!CollectionUtils.isEmpty(costDepartmentProfits)) {
                                filterProfit.addAll(costDepartmentProfits);
                            }
                        }
                    }
                    Map<Long, Integer> sortMap = reportFormList.stream().collect(Collectors.toMap(ReportForm::getId, ReportForm::getSort, (a, b) -> b));
                    Map<Long, String> descriptionMap = reportFormList.stream().collect(Collectors.toMap(ReportForm::getId, reportForm -> !StringUtils.isEmpty(reportForm.getDescription()) ? reportForm.getDescription() : "", (a, b) -> b));

                    List<CostProfitVo> costProfitVos = BeanUtil.convertList(filterProfit, CostProfitVo.class);
                    costProfitVos.forEach(profitVo -> {
                        profitVo.setDescription(descriptionMap.get(profitVo.getReportId()));
                        profitVo.setSort(sortMap.get(profitVo.getReportId()));
                        List<ReportForm> profitReportFormList = reportIdMap.get(profitVo.getReportId());
                        if (!CollectionUtils.isEmpty(profitReportFormList)) {
                            profitVo.setDataType(profitReportFormList.get(NumberConstant.ZERO).getDataType());
                            profitVo.setDecimalPlace(profitReportFormList.get(NumberConstant.ZERO).getDecimalPlace());
                            profitVo.setPermil(profitReportFormList.get(NumberConstant.ZERO).getPermil());
                            profitVo.setFontColor(profitReportFormList.get(NumberConstant.ZERO).getFontColor());
                        } else {
                            profitVo.setDataType(NumberConstant.ONE);
                            profitVo.setDecimalPlace(NumberConstant.TWO);
                            profitVo.setPermil(NumberConstant.ONE);
                        }
                    });
                    //记录所有月份的科室损益数据
                    allCostProfitVo.addAll(costProfitVos);
                    Map<Long, List<CostProfitVo>> collect = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getReportParentId));
                    List<CostProfitVo> costProfitParentVos = collect.get(NumberConstant.ZERO_L);
                    collect.remove(NumberConstant.ZERO_L);
                    for (CostProfitVo costProfitVo : costProfitParentVos) {
                        List<CostProfitVo> costProfitVo1 = collect.get(costProfitVo.getReportId());
                        if (!CollectionUtils.isEmpty(costProfitVo1)) {
                            costProfitVo.setChildren(setChildren(costProfitVo1, collect));
                        }
                    }
                    if (!CollectionUtils.isEmpty(costProfitParentVos)) {
                        costProfitParentVos.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo)));
                    }
                    BatchCostProfitResponse response = new BatchCostProfitResponse();
                    response.setComputeDate(computeDates);
                    response.setProfitVoList(costProfitParentVos);
                    response.setAllowDrillDown(true);
                    responses.add(response);
                }
                //获取月度汇总数据
                List<CostProfitVo> costProfitVos = generateSummaryForMultipleMonths(allCostProfitVo);
                if(!CollectionUtils.isEmpty(costProfitVos)){
                    BatchCostProfitResponse response = new BatchCostProfitResponse();
                    response.setComputeDate(String.format("%s至%s", beginComputeDate, endComputeDate));
                    response.setProfitVoList(costProfitVos);
                    response.setAllowDrillDown(false);
                    response.setMonthlyAccumulation(true);
                    responses.add(NumberConstant.ZERO,response);
                }
                return responses;

            } else {
                return responses;
            }
        }
    }

    /**
     * 获取树状结构的科室损益数据
     * @param costProfitVos
     * @return
     */
    public List<CostProfitVo> getCostProfitVoTree(List<CostProfitVo> costProfitVos){
        // 参数校验
        if (CollectionUtils.isEmpty(costProfitVos)) {
            return Collections.emptyList();
        }
        Map<Long, List<CostProfitVo>> collect = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getReportParentId));
        List<CostProfitVo> costProfitParentVos = collect.get(NumberConstant.ZERO_L);
        collect.remove(NumberConstant.ZERO_L);
        for (CostProfitVo costProfitVo : costProfitParentVos) {
            List<CostProfitVo> costProfitVo1 = collect.get(costProfitVo.getReportId());
            if (!CollectionUtils.isEmpty(costProfitVo1)) {
                costProfitVo.setChildren(setChildren(costProfitVo1, collect));
            }
        }
        if (!CollectionUtils.isEmpty(costProfitParentVos)) {
            costProfitParentVos.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo)));
        }
        return  costProfitParentVos;
    }

    /**
     * 生成多月份汇总的科室损益数据
     *
     * @param allCostProfitVo 原始数据列表
     * @return 汇总后的科室损益数据
     */
    private List<CostProfitVo> generateSummaryForMultipleMonths(List<CostProfitVo> allCostProfitVo){
        // 参数校验
        if (CollectionUtils.isEmpty(allCostProfitVo)) {
            return Collections.emptyList();
        }
        List<CostProfitVo> profitVoList=new ArrayList<>() ;
        Map<Long, List<CostProfitVo>> reportGroup = allCostProfitVo.stream().collect(Collectors.groupingBy(CostProfitVo::getReportId));
        reportGroup.forEach((reportId, profitVos) -> {
            CostProfitVo costProfitVo = BeanUtil.convertObj(profitVos.get(NumberConstant.ZERO), CostProfitVo.class);
            BigDecimal totalAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getAmount()).orElse(BigDecimal.ZERO))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal totalBudgetAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getBudgetAmount()).orElse(BigDecimal.ZERO))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal totalPrevPeriodAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getPrevPeriodAmount()).orElse(BigDecimal.ZERO))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal totalSamePeriodAmount = profitVos.stream().map(vo -> Optional.ofNullable(vo.getSamePeriodAmount()).orElse(BigDecimal.ZERO))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            costProfitVo.setAmount(totalAmount);
            costProfitVo.setBudgetAmount(totalBudgetAmount);
            costProfitVo.setPrevPeriodAmount(totalPrevPeriodAmount);
            costProfitVo.setSamePeriodAmount(totalSamePeriodAmount);
            costProfitVo.setCompletionRate(calculateRate(costProfitVo.getAmount(), costProfitVo.getBudgetAmount()));
            costProfitVo.setMomRate(calculateRate(costProfitVo.getAmount().subtract(costProfitVo.getPrevPeriodAmount()), costProfitVo.getPrevPeriodAmount()));
            costProfitVo.setYoyRate(calculateRate(costProfitVo.getAmount().subtract(costProfitVo.getSamePeriodAmount()), costProfitVo.getSamePeriodAmount()));
            profitVoList.add(costProfitVo);
        });
        //转成树状结构
        List<CostProfitVo> costProfitVoTree = getCostProfitVoTree(profitVoList);
        return costProfitVoTree;
    }


    @Override
    public Object getRedirectData(String computeDate, Long reportId, Long hospId, String reportType, String responsibilityCode) {
        //查询报表项目
        Integer year = ComputeDateUtils.getComputeYear(computeDate);
        Integer month = ComputeDateUtils.getComputeMonth(computeDate);
        LambdaQueryWrapper<ReportForm> reportFormQueryWrapper = new LambdaQueryWrapper<>();
        reportFormQueryWrapper.eq(ReportForm::getHospId, hospId);
        reportFormQueryWrapper.eq(ReportForm::getReportType, reportType);
        reportFormQueryWrapper.eq(ReportForm::getId, reportId);
        //这里所有配置都需要做特殊处理，为防程序报错及项目调整，已计算过的数据可能需要查询已作废的报表项目设置
        ReportForm one = reportFormService.getByReportId(hospId, reportType, reportId);
        if (Objects.isNull(one)) {
            throw new CostException("未找到报表id为【" + reportId + "】报表配置，请确认数据是否有调整");
        }
        Integer calcType = one.getCalcType();
        //查询关联关系
        Map<Long, List<ReportRelation>> reportRelationMap = reportRelationService.list(new QueryWrapper<ReportRelation>().lambda().eq(ReportRelation::getHospId, hospId)).stream().collect(Collectors.groupingBy(ReportRelation::getReportId));
        List<ReportRelation> reportRelations = reportRelationMap.get(reportId);
        if (CollectionUtils.isEmpty(reportRelations)) {
            throw new CostException("未找到报表id为【" + reportId + "】报表关系对应配置，请确认数据是否有调整");
        }
        //会计科目代码
        List<String> relations = reportRelations.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList());
        DecimalFormat df = new DecimalFormat("0.00%");
        if (calcType.equals(NumberConstant.ONE)) {
            // 归集后
            List<IncomeCollection> incomeList = incomeCollectionService.list(new QueryWrapper<IncomeCollection>().lambda()
                    .eq(IncomeCollection::getHospId, hospId)
                    .eq(year > 0, IncomeCollection::getYear, year).eq(month > 0, IncomeCollection::getMonth, month)
                    .eq(IncomeCollection::getResponsibilityCode, responsibilityCode));

            // 分摊后的数据说明是分摊后的数据 这里原有为收益中心数据 同步添加医技分摊后数据
            List<AllocationQuery> allocationQueryList = allocationQueryService.list(new QueryWrapper<AllocationQuery>().lambda().eq(AllocationQuery::getHospId, hospId)
                    .eq(year > 0, AllocationQuery::getDateYear, year)
                    .eq(month > 0, AllocationQuery::getDateMonth, month)
                    .eq(AllocationQuery::getTargetResponsibilityCode, responsibilityCode));

            // 封装数据
            List<AllocationQueryReportVO> allocationQueryReportVOList = BeanUtil.convertList(allocationQueryList, AllocationQueryReportVO.class);
            allocationQueryReportVOList.forEach(i -> {
                i.setAccountingCodes(Arrays.asList(i.getAccountingCode().split(StrUtil.COMMA)));
                i.setAccountingNames(Arrays.asList(i.getAccountingName().split(StrUtil.COMMA)));
            });
            //取会计科目字典
            List<Accounting> accountList1 = accountingService.getAccountList(hospId, relations);
            if (CollectionUtils.isEmpty(accountList1)) {
                throw new CostException("未找到会计科目字典");
            }
            // 查找在归集数据里面当前责任中心对应的这些会计科目的金额
            Map<String, List<IncomeCollection>> incomeCollect = new HashMap<>();
            if (!CollectionUtils.isEmpty(incomeList)) {
                List<IncomeCollection> incomeCollectionList = incomeList.stream().filter(income -> relations.contains(income.getAccountingCode())).collect(Collectors.toList());
                incomeCollect = incomeCollectionList.stream().collect(Collectors.groupingBy(IncomeCollection::getAccountingCode));

            }
            // 需要查询分摊后的表
            Map<String, List<AllocationQueryReportVO>> costCollect = new HashMap<>();
            if (!CollectionUtils.isEmpty(allocationQueryReportVOList)) {
                List<AllocationQueryReportVO> reportVOList = allocationQueryReportVOList.stream().filter(m -> relations.contains(m.getAccountingCode())).collect(Collectors.toList());
                costCollect = reportVOList.stream().collect(Collectors.groupingBy(AllocationQueryReportVO::getAccountingCode));

            }
            List<AccountAmountVo> list = new ArrayList<>();
            for (Accounting accounting : accountList1) {
                AccountAmountVo vo = new AccountAmountVo();
                vo.setAccountCode(accounting.getAccountingCode());
                vo.setAccountName(accounting.getAccountingName());
                List<IncomeCollection> incomeCollections = incomeCollect.get(accounting.getAccountingCode());
                AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.000000"));
                if (!CollectionUtils.isEmpty(incomeCollections)) {
                    incomeCollections.forEach(m -> {
                        sum.updateAndGet(v -> v.add(m.getAmount()));
                    });
                }
                List<AllocationQueryReportVO> costCollections = costCollect.get(accounting.getAccountingCode());
                if (!CollectionUtils.isEmpty(costCollections)) {
                    costCollections.forEach(m -> {
                        sum.updateAndGet(v -> v.add(m.getAmount()));
                    });
                }
                vo.setAmount(sum.get().setScale(2, RoundingMode.HALF_UP));
                list.add(vo);
            }
            return list;
        } else if (calcType.equals(NumberConstant.TWO)) {

            //分摊层级
//            List<Responsibility> list = responsibilityService.list(new QueryWrapper<Responsibility>()
//                    .lambda()
//                    .select(Responsibility::getResponsibilityCode, Responsibility::getResponsibilityName)
//                    .eq(Responsibility::getHospId, hospId).in(Responsibility::getShareId, relations));
//            if(CollectionUtils.isEmpty(list)){
//               throw new CostException(reportId+"下报表下，关联的分摊层级【"+relations+"】未找到责任中心数据");
//            }

            List<CostAccountShare> accountShares = costAccountShareService.getAll();
            if (CollectionUtils.isEmpty(accountShares)) {
                throw new CostException("成本分摊参数对应不存在");
            }
            Map<Long, CostAccountShare> accountShareMap = accountShares.stream().collect(Collectors.toMap(CostAccountShare::getId, accountShare -> accountShare, (a, b) -> b));

//            List<String> collect = list.stream().map(Responsibility::getResponsibilityCode).collect(Collectors.toList());
            List<Allocation> allocationList = allocationService.list(new QueryWrapper<Allocation>()
                    .lambda()
                    .eq(Allocation::getHospId, hospId)
                    .eq(year > 0, Allocation::getDateYear, year)
                    .eq(month > 0, Allocation::getDateMonth, month)
                    .eq(Allocation::getTargetResponsibilityCode, responsibilityCode)
                    .in(Allocation::getShareLevelId, relations));

            List<AllocationReportVO> allocationReportVOS = BeanUtil.convertList(allocationList, AllocationReportVO.class);
            for (AllocationReportVO allocationReportVO : allocationReportVOS) {
                CostAccountShare costAccountShare = accountShareMap.get(allocationReportVO.getAccountShareId());
                if (Objects.nonNull(costAccountShare)) {
                    String paramList = costAccountShare.getParamList();
                    if (!StringUtils.isEmpty(paramList)) {
                        List<AccountShareVO> accountShareVOs = JacksonUtil.str2ObjList(paramList, List.class, AccountShareVO.class);
                        if (!CollectionUtils.isEmpty(accountShareVOs)) {
                            Map<String, String> shareParamPercentMap = accountShareVOs.stream().collect(Collectors.toMap(AccountShareVO::getShareParamCode, AccountShareVO::getShareParamPopout, (a, b) -> b));
                            String s = shareParamPercentMap.get(allocationReportVO.getShareParamCode());
                            if (!StringUtils.isEmpty(s)) {
                                allocationReportVO.setShareParamPercent(new BigDecimal(s).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
                            }
                        }
                    }
                    String alias = costAccountShare.getAlias();
                    if (StringUtils.isEmpty(alias)) {
                        allocationReportVO.setAlias(costAccountShare.getAccountingNames());
                    } else {
                        allocationReportVO.setAlias(alias);

                    }
                }
            }
            Map<String, List<AllocationReportVO>> collect1 = allocationReportVOS.stream().collect(Collectors.groupingBy(AllocationReportVO::getResponsibilityCode));
            List<CostProfitRedirectResponse> responses = new ArrayList<>();
            collect1.forEach((k, v) -> {
                CostProfitRedirectResponse response = new CostProfitRedirectResponse();
                Map<String, List<AllocationReportVO>> aliasCollect = v.stream().collect(Collectors.groupingBy(AllocationReportVO::getAlias));
                List<CostProfitRedirectAliasVo> aliasVos = new ArrayList<>();
                aliasCollect.forEach((k1, v1) -> {
                    CostProfitRedirectAliasVo redirectAliasVo = new CostProfitRedirectAliasVo();
                    AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.0000"));
                    List<CostProfitRedirectDataVo> dataVoList = new ArrayList<>();
                    v1.forEach(f -> {
                        CostProfitRedirectDataVo dataVo = new CostProfitRedirectDataVo();
                        BigDecimal shareParamPercent = f.getShareParamPercent();
                        if (shareParamPercent != null) {
                            dataVo.setShareParamAmount(f.getTotalAmount().multiply(shareParamPercent).setScale(2, RoundingMode.HALF_UP));
                            dataVo.setShareParamName(f.getShareParamName() + "(" + df.format(shareParamPercent) + ")");
                        }
                        dataVo.setShareParamCode(f.getShareParamCode());
                        dataVo.setShareParamNum(f.getShareParamValueNum());
                        dataVo.setShareParamRate(df.format(f.getShareParamRate()));
                        dataVo.setShareParamValue(f.getAmount());
                        sum.updateAndGet(i -> i.add(f.getTotalAmount()));
                        redirectAliasVo.setAlias(k1 + "(" + f.getTotalAmount().setScale(2, RoundingMode.HALF_UP) + ")");
                        dataVoList.add(dataVo);
                    });
//                    if(!CollectionUtils.isEmpty(dataVoList)){
//                        for (CostProfitRedirectDataVo dataVo : dataVoList) {
//                            if(sum.get().compareTo(BigDecimal.ZERO.setScale(4,RoundingMode.HALF_UP))==0){
//                                dataVo.setShareParamName(dataVo.getShareParamName()+"0.0000");
//                            }else {
//                                BigDecimal divide = dataVo.getShareParamAmount().divide(sum.get(), 2, RoundingMode.HALF_UP);
//                                dataVo.setShareParamName(dataVo.getShareParamName());
//                            }
//                        }
//                    }
//                    redirectAliasVo.setAlias(k1+"("+sum.get()+")");
                    redirectAliasVo.setShareParamData(dataVoList);
                    aliasVos.add(redirectAliasVo);
                });
                response.setResponseCode(k);
                response.setResponseName(v.get(0).getResponsibilityName());
                response.setDataList(aliasVos);
                responses.add(response);
            });
            return responses;
        } else if (calcType.equals(NumberConstant.FIVE)) {
            //责任中心
            List<CostAccountShare> accountShares = costAccountShareService.getAll();
            if (CollectionUtils.isEmpty(accountShares)) {
                throw new CostException("成本分摊参数对应不存在");
            }
            Map<Long, CostAccountShare> accountShareMap = accountShares.stream().collect(Collectors.toMap(CostAccountShare::getId, accountShare -> accountShare, (a, b) -> b));
            List<Allocation> allocationList = allocationService.list(new QueryWrapper<Allocation>()
                    .lambda()
                    .eq(Allocation::getHospId, hospId)
                    .eq(year > 0, Allocation::getDateYear, year)
                    .eq(month > 0, Allocation::getDateMonth, month)
                    .eq(Allocation::getTargetResponsibilityCode, responsibilityCode)
                    .in(Allocation::getResponsibilityCode, relations));

            List<AllocationReportVO> allocationReportVOS = BeanUtil.convertList(allocationList, AllocationReportVO.class);

            for (AllocationReportVO allocationReportVO : allocationReportVOS) {
                CostAccountShare costAccountShare = accountShareMap.get(allocationReportVO.getAccountShareId());
                if (Objects.nonNull(costAccountShare)) {
                    String paramList = costAccountShare.getParamList();
                    if (!StringUtils.isEmpty(paramList)) {
                        List<AccountShareVO> accountShareVOs = JacksonUtil.str2ObjList(paramList, List.class, AccountShareVO.class);
                        if (!CollectionUtils.isEmpty(accountShareVOs)) {
                            Map<String, String> shareParamPercentMap = accountShareVOs.stream().collect(Collectors.toMap(AccountShareVO::getShareParamCode, AccountShareVO::getShareParamPopout, (a, b) -> b));
                            String s = shareParamPercentMap.get(allocationReportVO.getShareParamCode());
                            if (!StringUtils.isEmpty(s)) {
                                allocationReportVO.setShareParamPercent(new BigDecimal(s).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
                            }
                        }
                    }
                    String alias = costAccountShare.getAlias();
                    if (StringUtils.isEmpty(alias)) {
                        allocationReportVO.setAlias(costAccountShare.getAccountingNames());
                    } else {
                        allocationReportVO.setAlias(alias);
                    }
                }
            }
            Map<String, List<AllocationReportVO>> collect1 = allocationReportVOS.stream().collect(Collectors.groupingBy(AllocationReportVO::getResponsibilityCode));
            List<CostProfitRedirectResponse> responses = new ArrayList<>();
            collect1.forEach((k, v) -> {
                CostProfitRedirectResponse response = new CostProfitRedirectResponse();
                Map<String, List<AllocationReportVO>> aliasCollect = v.stream().collect(Collectors.groupingBy(AllocationReportVO::getAlias));
                List<CostProfitRedirectAliasVo> aliasVos = new ArrayList<>();
                aliasCollect.forEach((k1, v1) -> {
                    CostProfitRedirectAliasVo redirectAliasVo = new CostProfitRedirectAliasVo();
                    AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.0000"));
                    List<CostProfitRedirectDataVo> dataVoList = new ArrayList<>();
                    v1.forEach(f -> {
                        CostProfitRedirectDataVo dataVo = new CostProfitRedirectDataVo();
                        BigDecimal shareParamPercent = f.getShareParamPercent();
                        if (shareParamPercent != null) {
                            dataVo.setShareParamAmount(f.getTotalAmount().multiply(shareParamPercent));
                            dataVo.setShareParamName(f.getShareParamName() + "(" + df.format(shareParamPercent) + ")");
                        }
                        dataVo.setShareParamCode(f.getShareParamCode());
//                        dataVo.setShareParamName(f.getShareParamName());
                        dataVo.setShareParamNum(f.getShareParamValueNum());
                        dataVo.setShareParamRate(df.format(f.getShareParamRate()));
                        dataVo.setShareParamValue(f.getAmount());
                        sum.updateAndGet(i -> i.add(f.getTotalAmount()));
                        redirectAliasVo.setAlias(k1 + "(" + f.getTotalAmount().setScale(2, RoundingMode.HALF_UP) + ")");
                        dataVoList.add(dataVo);
                    });

//                    if (!CollectionUtils.isEmpty(dataVoList)) {
//                        for (CostProfitRedirectDataVo dataVo : dataVoList) {
//                            if (sum.get().compareTo(BigDecimal.ZERO.setScale(4, RoundingMode.HALF_UP)) == 0) {
//                                dataVo.setShareParamName(dataVo.getShareParamName() + "0.0000");
//                            } else {
//                                BigDecimal divide = dataVo.getShareParamAmount().divide(sum.get(), 2, RoundingMode.HALF_UP);
////                                dataVo.setShareParamName(dataVo.getShareParamName()+"("+divide+")");
//                                dataVo.setShareParamName(dataVo.getShareParamName());
//
//                            }
//                        }
//                    }
                    redirectAliasVo.setShareParamData(dataVoList);
                    aliasVos.add(redirectAliasVo);
                });
                response.setResponseCode(k);
                response.setResponseName(v.get(0).getResponsibilityName());
                response.setDataList(aliasVos);
                responses.add(response);
            });
            return responses;
        }
        return new ArrayList<>();
    }

    @Override
    public Object getComputeProfitCollect(String computeDate, Long hospId, String reportType) {
        Integer year = ComputeDateUtils.getComputeYear(computeDate);
        Integer month = ComputeDateUtils.getComputeMonth(computeDate);
        Integer integerReportType = Integer.valueOf(reportType);
        DictDataVo dataVo = getDictDataVo(reportType);
        Long id = Long.valueOf(dataVo.getExpandOne());
        List<Responsibility> responsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
                .eq(Responsibility::getHospId, hospId)
                .eq(Responsibility::getShareId, id)
                .and(q -> q.eq(Responsibility::getStatus, NumberConstant.ONE).or().eq(Responsibility::getStatus, null)));

        if (CollectionUtils.isEmpty(responsibilityList)) {
            throw new CostException("未找到对应分摊层级责任中心");
        }
        //获取授权的责任中心
        responsibilityList = userResponsibilityRightService.getAuthorizedResponsibility(responsibilityList);
        List<Responsibility> responsibilityAllList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
                .eq(Responsibility::getHospId, hospId));
        Map<Long, Responsibility> map = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getId, responsibility -> responsibility, (a, b) -> b));
        List<Responsibility> addList = new ArrayList<>();
        for (Responsibility responsibility : responsibilityList) {
            Responsibility responsibility1 = map.get(responsibility.getParentId());
            if (Objects.nonNull(responsibility1)) {
                addList.add(responsibility1);
                if (!responsibility1.getParentId().equals(NumberConstant.ZERO_L)) {
                    getResponsibilityParent(responsibility1, map, addList);
                }
            }
        }
        if (!CollectionUtils.isEmpty(addList)) {
            //去重
            List<Responsibility> collect = addList.stream().distinct().collect(Collectors.toList());
            responsibilityList.addAll(collect);
        }
        //找出最外层用于出参循环
        Map<Long, List<Responsibility>> responsibilityGroup = responsibilityList.stream().collect(Collectors.groupingBy(Responsibility::getParentId));
        List<Responsibility> responseParent = responsibilityList.stream().filter(f -> f.getParentId().equals(NumberConstant.ZERO_L)).collect(Collectors.toList());
        //只留下中间责任中心
        responsibilityList.removeAll(responseParent);
        List<CommonResponsibilityReportVo> list = new ArrayList<>();
        for (Responsibility responsibility : responseParent) {
            CommonResponsibilityReportVo commonResponsibilityReportVo = new CommonResponsibilityReportVo();
            commonResponsibilityReportVo.setResponsibilityCode(responsibility.getResponsibilityCode());
            commonResponsibilityReportVo.setResponsibilityName(responsibility.getResponsibilityName());
            commonResponsibilityReportVo.setSort(responsibility.getSort());
            List<Responsibility> responsibilities = responsibilityGroup.get(responsibility.getId());
            if (!CollectionUtils.isEmpty(responsibilities)) {
                commonResponsibilityReportVo.setChild(getChildTitle(responsibilities, responsibilityGroup));
            } else {
                //要显示占比时自动生成默认金额占比层
                if (IsShowPercent()) {
                    commonResponsibilityReportVo.setChild(setDefalutChildList(responsibility));
                } else {
                    //不显示占比时，直接责任中心作为金额层
                    commonResponsibilityReportVo.setResponsibilityCode(commonResponsibilityReportVo.getResponsibilityCode() + AMOUNT_FIELD);
                }

            }
            list.add(commonResponsibilityReportVo);
        }
        ComputeProfitCollectResponse response = new ComputeProfitCollectResponse();
        commonResponsibilityReportVoSort(list);
        response.setTitle(list);

        List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
                .eq(ReportForm::getHospId, hospId)
                .eq(ReportForm::getReportType, integerReportType).eq(ReportForm::getHide, NumberConstant.ONE));
        if (CollUtil.isEmpty(reportFormList)) {
            throw new CostException(500, "【" + integerReportType + "】损益表配置未找到");
        }

        List<ReportFormCustomVo> reportFormCustomVos = BeanUtil.convertList(reportFormList, ReportFormCustomVo.class);


        List<CostDepartmentProfit> departmentProfits = this.list(new QueryWrapper<CostDepartmentProfit>().lambda()
                .eq(CostDepartmentProfit::getHospId, hospId)
                .eq(CostDepartmentProfit::getYear, year)
                .eq(CostDepartmentProfit::getMonth, month)
                .eq(CostDepartmentProfit::getShareType, integerReportType));


        List<CostProfitVo> costProfitVos = BeanUtil.convertList(departmentProfits, CostProfitVo.class);
        //按责任中心-reportId进行分组
        Map<Long, List<CostProfitVo>> collect2 = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getReportId));
        DecimalFormat df = new DecimalFormat("0.00%");
        Map<Long, List<ReportVo>> reportDataMap = new HashMap<>();
        collect2.forEach((k, v) -> {
            List<ReportVo> reportVos = new ArrayList<>();
            v.forEach(f -> {
                ReportVo amount = new ReportVo();
                amount.setCode(f.getResponsibilityCode() + AMOUNT_FIELD);
                amount.setValue(f.getAmount());
                reportVos.add(amount);
                ReportVo percent = new ReportVo();
                percent.setCode(f.getResponsibilityCode() + PERCENT_FIELD);
                if (f.getPercent() != null) {
                    percent.setValue(df.format(f.getPercent()));
                } else {
                    percent.setValue("");
                }
                reportVos.add(percent);
            });
            reportDataMap.put(k, reportVos);
        });

        for (ReportFormCustomVo reportFormCustomVo : reportFormCustomVos) {
            List<ReportVo> reportVos = reportDataMap.get(reportFormCustomVo.getId());
            if (!CollectionUtils.isEmpty(responsibilityGroup)) {
                reportFormCustomVo.setData(reportVos);
            }
        }


        Map<Long, List<ReportFormCustomVo>> collect = reportFormCustomVos.stream().collect(Collectors.groupingBy(ReportFormCustomVo::getParentId));

        List<ReportFormCustomVo> costProfitVos1 = collect.get(0L);
        collect.remove(NumberConstant.ZERO_L);
        //最外层排序
        if (!CollectionUtils.isEmpty(costProfitVos1)) {
            costProfitVos1.sort(Comparator.comparing(ReportFormCustomVo::getSort, Comparator.nullsLast(Integer::compareTo)));
        }
        for (ReportFormCustomVo costProfitVo : costProfitVos1) {
            List<ReportFormCustomVo> costProfitVo1 = collect.get(costProfitVo.getId());
            if (!CollectionUtils.isEmpty(costProfitVo1)) {
                //子项排序
                costProfitVo1.sort(Comparator.comparing(ReportFormCustomVo::getSort, Comparator.nullsLast(Integer::compareTo)));
                costProfitVo.setChildren(setCustomChildren(costProfitVo1, collect));
            }
        }


        response.setData(costProfitVos1);
        return response;


//
//
//
//        //取一行数据 作为父类模版
//        Set<Map.Entry<String, List<CostProfitVo>>> entrySet = responseGroup.entrySet();
//        Map.Entry<String, List<CostProfitVo>> firstEntry = entrySet.iterator().next();
//        List<CostProfitVo> parentModel = firstEntry.getValue();
//        //备注：所有记算过的数据都是最后一层责任中心，所以按最后一层责任 中心 找出所有上级责任中心后 给模版添加到上层责任中心
//        //按报表类型 取字典
//        DictDataVo dataVo = getDictDataVo(reportType);
//        Long id = Long.valueOf(dataVo.getExpandOne());
//
//        //按字典给护 的 分摊层级id 查找对应报表 的责任中心 找出的是没有父类的
//        List<Responsibility> responsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
//                .eq(Responsibility::getHospId, hospId)
//                .eq(Responsibility::getShareId, id));
//        if (CollectionUtils.isEmpty(responsibilityList)) {
//            throw new CostException("未找到对应分摊层级责任中心");
//        }
//        //获取当前院区所有的责任中心
//        List<Responsibility> responsibilityAllList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
//                .eq(Responsibility::getHospId, hospId));
//        Map<Long, Responsibility> map = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getId, responsibility -> responsibility, (a, b) -> b));
//        Map<String, Long> responseCodeParentIdMap = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getParentId, (a, b) -> b));
//        Map<String, String> responseNameMap = responsibilityAllList.stream().collect(Collectors.toMap(Responsibility::getResponsibilityCode, Responsibility::getResponsibilityName, (a, b) -> b));
//
//
//        //通过查询的最下层责任中心 找到其所有父类责任中心
//        List<Responsibility> parentResponseList = new ArrayList<>();
//        for (Responsibility responsibility : responsibilityList) {
//            if (responsibility.getParentId().equals(NumberConstant.ZERO_L)) {
//                parentResponseList.add(responsibility);
//            } else {
//                Responsibility responsibility1 = map.get(responsibility.getParentId());
//                if (Objects.nonNull(responsibility1)) {
//                    parentResponseList.add(responsibility1);
//                    if (!responsibility1.getParentId().equals(NumberConstant.ZERO_L)) {
//                        getResponsibilityParent(responsibility1, map, parentResponseList);
//                    }
//                }
//            }
//
//        }
//        //去除重复组装数据
//        List<Responsibility> parentResponsibility = parentResponseList.stream().distinct().collect(Collectors.toList());
//        //找出最外层用于出参循环
//        List<Responsibility> responseParent = parentResponsibility.stream().filter(f -> f.getParentId().equals(NumberConstant.ZERO_L)).collect(Collectors.toList());
//        //只留下中间责任中心
//        parentResponsibility.removeAll(responseParent);
//
//        //最上级添加模版
//        List<CostProfitVo> parentReportVos = new ArrayList<>();
//        for (Responsibility responsibility : responseParent) {
//            List<CostProfitVo> profitVos = BeanUtil.convertList(parentModel, CostProfitVo.class);
//            for (CostProfitVo costProfitVo : profitVos) {
//                costProfitVo.setResponsibilityCode(responsibility.getResponsibilityCode());
//                costProfitVo.setResponsibilityName(responsibility.getResponsibilityName());
//                costProfitVo.setAmount(BigDecimal.ZERO);
//                costProfitVo.setPercent(BigDecimal.ZERO);
//                parentReportVos.add(costProfitVo);
//            }
//        }
//
//        //中间责任中心 添加模版 添加父类责任中心
//        List<CostProfitVo> middleReportVos = new ArrayList<>();
//        for (Responsibility responsibility : parentResponsibility) {
//            List<CostProfitVo> profitVos = BeanUtil.convertList(parentModel, CostProfitVo.class);
//            Long aLong = responseCodeParentIdMap.get(responsibility.getResponsibilityCode());
//            for (CostProfitVo costProfitVo : profitVos) {
//                costProfitVo.setResponsibilityCode(responsibility.getResponsibilityCode());
//                costProfitVo.setResponsibilityName(responsibility.getResponsibilityName());
//                costProfitVo.setAmount(BigDecimal.ZERO);
//                costProfitVo.setPercent(BigDecimal.ZERO);
//                if (aLong.equals(NumberConstant.ZERO_L)) {
//                    costProfitVo.setParentResponsibilityCode(responsibility.getResponsibilityCode());
//                    costProfitVo.setParentResponsibilityName(responsibility.getResponsibilityName());
//                } else {
//                    Responsibility responsibility1 = map.get(aLong);
//                    if (Objects.nonNull(responsibility1)) {
//                        costProfitVo.setParentResponsibilityCode(responsibility1.getResponsibilityCode());
//                        costProfitVo.setParentResponsibilityName(responsibility1.getResponsibilityName());
//                    }
//                }
//                middleReportVos.add(costProfitVo);
//            }
//        }
//        //添加父类责任中心
//        //已计算过的数据添加上级责任中心
//        for (CostProfitVo departmentProfit : costProfitVos) {
//            Long aLong = responseCodeParentIdMap.get(departmentProfit.getResponsibilityCode());
//            if (aLong != null) {
//                if (aLong.equals(NumberConstant.ZERO_L)) {
////                    Long aLong1 = responseCodeIdMap.get(departmentProfit.getResponsibilityCode());
//                    departmentProfit.setParentResponsibilityCode(departmentProfit.getResponsibilityCode());
//                    departmentProfit.setParentResponsibilityName(departmentProfit.getResponsibilityName());
//                } else {
//                    Responsibility responsibility = map.get(aLong);
//                    if (Objects.nonNull(responsibility)) {
//                        departmentProfit.setParentResponsibilityCode(responsibility.getResponsibilityCode());
//                        departmentProfit.setParentResponsibilityName(responsibility.getResponsibilityName());
//                    }
//                }
//            }
//        }
//        //已计算过的 按责任中心-报表id 分组
//        Map<String, Map<Long, List<CostProfitVo>>> sumGroup = new HashMap<>();
//        //已计算过的 按父类责任中心分组
//        Map<String, List<CostProfitVo>> collect1 = costProfitVos.stream().collect(Collectors.groupingBy(CostProfitVo::getParentResponsibilityCode));
//        if (!CollectionUtils.isEmpty(collect1)) {
//            collect1.forEach((k, v) -> {
//                Map<Long, List<CostProfitVo>> collect2 = v.stream().collect(Collectors.groupingBy(CostProfitVo::getReportId));
//                sumGroup.put(k, collect2);
//            });
//        }
//
//        //计算所有中间层
//        List<CostProfitVo> middleFilterReportVos = new ArrayList<>();
//        for (CostProfitVo middleReportVo : middleReportVos) {
//            String responsibilityCode = middleReportVo.getResponsibilityCode();
//            Map<Long, List<CostProfitVo>> longListMap = sumGroup.get(responsibilityCode);
//            if (!CollectionUtils.isEmpty(longListMap)) {
//                List<CostProfitVo> profitVos = longListMap.get(middleReportVo.getReportId());
//                AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.0000"));
//                if (!CollectionUtils.isEmpty(profitVos)) {
//                    profitVos.forEach(m -> {
//                        sum.updateAndGet(v -> v.add(m.getAmount()));
//                    });
//
//                    middleReportVo.setAmount(sum.get());
//                }
//            } else {
//                //未在最下层找到数据的可能还是一个分类 提取出来
//                middleFilterReportVos.add(middleReportVo);
//            }
//        }
//        //用于处理多层级中 有两层中间层的数据
//        if (!CollectionUtils.isEmpty(middleFilterReportVos)) {
//            handleMiddleFilterReport(middleReportVos, middleFilterReportVos);
//        }
//        Map<String, Map<Long, List<CostProfitVo>>> sumMiddleGroup = new HashMap<>();
//        Map<String, List<CostProfitVo>> collect2 = middleReportVos.stream().collect(Collectors.groupingBy(CostProfitVo::getParentResponsibilityCode));
//        if (!CollectionUtils.isEmpty(collect2)) {
//            collect2.forEach((k, v) -> {
//                Map<Long, List<CostProfitVo>> collect3 = v.stream().collect(Collectors.groupingBy(CostProfitVo::getReportId));
//                sumMiddleGroup.put(k, collect3);
//            });
//        }
//
//        // 最上层的需要执行两次分组 两层时取最后一层计算 多层时取 中间层计算合计
//        for (CostProfitVo parentReportVo : parentReportVos) {
//            String responsibilityCode = parentReportVo.getResponsibilityCode();
//            Map<Long, List<CostProfitVo>> longListMap = sumGroup.get(responsibilityCode);
//            //在最下层找到的 说明是两层
//            if (!CollectionUtils.isEmpty(longListMap)) {
//                List<CostProfitVo> profitVos = longListMap.get(parentReportVo.getReportId());
//                AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.0000"));
//                if (!CollectionUtils.isEmpty(profitVos)) {
//                    profitVos.forEach(m -> {
//                        sum.updateAndGet(v -> v.add(m.getAmount()));
//                    });
//                }
//                //再找中间层是否存在子类
//                Map<Long, List<CostProfitVo>> longListMap1 = sumMiddleGroup.get(responsibilityCode);
//                if (!CollectionUtils.isEmpty(longListMap1)) {
//                    List<CostProfitVo> profitVos1 = longListMap1.get(parentReportVo.getReportId());
//                    if (!CollectionUtils.isEmpty(profitVos1)) {
//                        profitVos1.forEach(m -> {
//                            sum.updateAndGet(v -> v.add(m.getAmount()));
//                        });
//                    }
//                }
//                parentReportVo.setAmount(sum.get());
//            } else {
//                //未在最下层找到从中间层找进行计算
//                Map<Long, List<CostProfitVo>> longListMap1 = sumMiddleGroup.get(responsibilityCode);
//                if (!CollectionUtils.isEmpty(longListMap1)) {
//                    List<CostProfitVo> profitVos = longListMap1.get(parentReportVo.getReportId());
//                    AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.0000"));
//                    if (!CollectionUtils.isEmpty(profitVos)) {
//                        profitVos.forEach(m -> {
//                            sum.updateAndGet(v -> v.add(m.getAmount()));
//                        });
//                    }
//                    parentReportVo.setAmount(sum.get());
//                }
//            }
//        }
//        //把最上层 中间层 最下层组装成一个list  进行分组
//
//        //组装数据
//        Map<String, List<CostProfitVo>> collect3 = parentReportVos.stream().collect(Collectors.groupingBy(CostProfitVo::getResponsibilityCode));
//        List<CostResponsibilityProfitVo> list = new ArrayList<>();
//        collect3.forEach((k, v) -> {
//            CostResponsibilityProfitVo vo = new CostResponsibilityProfitVo();
////            List<CostProfitVo> costProfitVos1 = collect3.get(s);
//            vo.setResponsibilityCode(k);
//            vo.setResponsibilityName(responseNameMap.get(k));
//            if (!CollectionUtils.isEmpty(v)) {
//                List<CommonDataReportVo> dataReportVos = new ArrayList<>();
//                for (CostProfitVo costProfitVo : v) {
//                    CommonDataReportVo vo1 = new CommonDataReportVo();
//                    vo1.setReportId(costProfitVo.getReportId());
//                    vo1.setValue(costProfitVo.getAmount());
//                    dataReportVos.add(vo1);
//                }
//                vo.setProfitList(dataReportVos);
//            } else {
//                vo.setProfitList(new ArrayList<>());
//            }
//            list.add(vo);
//        });
//        middleReportVos.addAll(costProfitVos);
//        Map<String, List<CostProfitVo>> collect5 = middleReportVos.stream().collect(Collectors.groupingBy(CostProfitVo::getResponsibilityCode));
//        List<CostResponsibilityProfitVo> list1 = new ArrayList<>();
//        collect5.forEach((k, v) -> {
//            CostResponsibilityProfitVo vo = new CostResponsibilityProfitVo();
//            vo.setResponsibilityCode(k);
//            vo.setResponsibilityName(responseNameMap.get(k));
//            if (!CollectionUtils.isEmpty(v)) {
//                vo.setParentResponsibilityCode(v.get(0).getParentResponsibilityCode());
//                List<CommonDataReportVo> dataReportVos = new ArrayList<>();
//                for (CostProfitVo costProfitVo : v) {
//                    CommonDataReportVo vo1 = new CommonDataReportVo();
//                    vo1.setReportId(costProfitVo.getReportId());
//                    vo1.setValue(costProfitVo.getAmount());
//                    dataReportVos.add(vo1);
//                }
//                vo.setProfitList(dataReportVos);
//            } else {
//                vo.setProfitList(new ArrayList<>());
//            }
//            list1.add(vo);
//        });
//        Map<String, List<CostResponsibilityProfitVo>> collect4 = list1.stream().collect(Collectors.groupingBy(CostResponsibilityProfitVo::getParentResponsibilityCode));
//        for (CostResponsibilityProfitVo vo : list) {
//            List<CostResponsibilityProfitVo> list2 = collect4.get(vo.getResponsibilityCode());
//            if (!CollectionUtils.isEmpty(list2)) {
//                if (!list2.get(0).getResponsibilityCode().equals(vo.getResponsibilityCode())) {
//                    vo.setChild(setProfitChildren(list2, collect4));
//                }
//            }
//        }
//        response.setData(list);
//
//        //提取出最上层
//
//
//        return response;

    }

    /**
     * 是否显示占比
     *
     * @return
     */
    public boolean IsShowPercent() {
        String parameterValue = centerService.getParameterValue(ParameterConstant.SHOW_PERCENT);
        return NumberConstant.ONE_S.equals(parameterValue);
    }

    /**
     * 是否需要代码计算
     * @return
     */
    public boolean IsNeedCalc(String reportType) {
        String parameterValue = centerService.getParameterValue(ParameterConstant.SQL_CALC_REPORT_TYPE);
        if(StringUtils.isEmpty(parameterValue)){
            return true;
        }
        //不需计算的报表类型列表
        List<String> nonCalcReportTypeList = Arrays.stream(parameterValue.split(SplitConstant.SEPARATOR_VERTICALLINE)).collect(Collectors.toList());
        return !nonCalcReportTypeList.contains(reportType);
    }

    private List<CommonResponsibilityReportVo> getChildTitle(List<Responsibility> responsibilities, Map<Long, List<Responsibility>> responsibilityGroup) {
        List<CommonResponsibilityReportVo> list = new ArrayList<>();
        for (Responsibility responsibility : responsibilities) {
            CommonResponsibilityReportVo commonResponsibilityReportVo = new CommonResponsibilityReportVo();
            commonResponsibilityReportVo.setResponsibilityCode(responsibility.getResponsibilityCode());
            commonResponsibilityReportVo.setResponsibilityName(responsibility.getResponsibilityName());
            commonResponsibilityReportVo.setSort(responsibility.getSort());
            List<Responsibility> responsibilityChild = responsibilityGroup.get(responsibility.getId());
            if (!CollectionUtils.isEmpty(responsibilityChild)) {
                commonResponsibilityReportVo.setChild(getChildTitle(responsibilityChild, responsibilityGroup));
            } else {
//                //添加金额占比
//                commonResponsibilityReportVo.setChild(setDefalutChildList(responsibility));
                //要显示占比时自动生成默认金额占比层
                if (IsShowPercent()) {
                    commonResponsibilityReportVo.setChild(setDefalutChildList(responsibility));
                } else {
                    //不显示占比时，直接责任中心作为金额层
                    commonResponsibilityReportVo.setResponsibilityCode(commonResponsibilityReportVo.getResponsibilityCode() + AMOUNT_FIELD);
                }
            }
            list.add(commonResponsibilityReportVo);
        }
        return list;


    }

    private @NotNull List<CommonResponsibilityReportVo> setDefalutChildList(Responsibility responsibility) {
        List<CommonResponsibilityReportVo> childList = new ArrayList<>();
        CommonResponsibilityReportVo amount = new CommonResponsibilityReportVo();
        amount.setResponsibilityCode(responsibility.getResponsibilityCode() + AMOUNT_FIELD);
        amount.setResponsibilityName(AMOUNT);
        amount.setSort(1);
        childList.add(amount);
        CommonResponsibilityReportVo percent = new CommonResponsibilityReportVo();
        percent.setResponsibilityCode(responsibility.getResponsibilityCode() + PERCENT_FIELD);
        percent.setResponsibilityName(PERCENT);
        percent.setSort(2);
        childList.add(percent);
        return childList;
    }

    private List<CostProfitVo> setChildren(List<CostProfitVo> child, Map<Long, List<CostProfitVo>> collect) {
        for (CostProfitVo costProfitVo : child) {
            if (!CollectionUtils.isEmpty(collect.get(costProfitVo.getReportId()))) {
                costProfitVo.setChildren(setChildren(collect.get(costProfitVo.getReportId()), collect));
            }
        }
        if (!CollectionUtils.isEmpty(child)) {
            child.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo)));
        }
        return child;
    }

    private List<ReportFormCustomVo> setCustomChildren(List<ReportFormCustomVo> child, Map<Long, List<ReportFormCustomVo>> collect) {
        for (ReportFormCustomVo costProfitVo : child) {
            if (!CollectionUtils.isEmpty(collect.get(costProfitVo.getId()))) {
                costProfitVo.setChildren(setCustomChildren(collect.get(costProfitVo.getId()), collect));
            }
        }
        if (!CollectionUtils.isEmpty(child)) {

            child.sort(Comparator.comparing(ReportFormCustomVo::getSort, Comparator.nullsLast(Integer::compareTo)));
        }
        return child;
    }

    /**
     * 按照会计科目进行计算
     *
     * @param i
     */
    private BigDecimal setAccountReportData(CostDepartmentProfitVO i, List<IncomeCollection> list, List<AllocationQueryReportVO> allocationQueryReportVOList, Map<Long, List<ReportRelation>> reportRelationMap, List<CostDepartmentProfitVO> allList) {
        // 在报表关联里面查询当前报表关联的
        Long reportId = i.getReportId();
        List<ReportRelation> reportRelationList = reportRelationMap.get(reportId);
        AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.000"));
        if (CollUtil.isNotEmpty(reportRelationList)) {
            // 获取对应的会计科目信息  筛选会计科目的Code
            List<String> accountList = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList());
            // 查找在归集数据里面当前责任中心对应的这些会计科目的金额
            List<IncomeCollection> incomeCollectionList = list.stream().filter(income -> income.getResponsibilityCode().equals(i.getResponsibilityCode()) && accountList.contains(income.getAccountingCode())).collect(Collectors.toList());
            // 需要查询分摊后的表
            List<AllocationQueryReportVO> reportVOList = allocationQueryReportVOList.stream().filter(m -> m.getTargetResponsibilityCode().equals(i.getResponsibilityCode()) && accountList.contains(m.getAccountingCode())).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(incomeCollectionList)) {
                incomeCollectionList.forEach(m -> {
                    sum.updateAndGet(v -> v.add(m.getAmount()));
                });
            }
            // 成本减
            if (CollUtil.isNotEmpty(reportVOList)) {
                reportVOList.forEach(m -> {
                    sum.updateAndGet(v -> v.add(m.getAmount()));
                });
            }
        }
//        i.setAmount(new BigDecimal(sum.toString()));
//        numMap.put(i.getReportNum()+i.getResponsibilityCode(),new BigDecimal(sum.toString()));
        return sum.get();
    }

    /**
     * 按照分摊层级进行计算
     * 按照分摊层级计算  报表分摊层级是当前的层级  并且目标责任中心失败当前责任中心
     */
    private BigDecimal setShareLevelReportData(CostDepartmentProfitVO i, List<CostShareLevel> costShareLevelList,
                                               Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList, List<CostDepartmentProfitVO> allList) {
        List<ReportRelation> reportRelationList = reportRelationMap.get(i.getReportId());
        AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.000"));
        if (CollUtil.isNotEmpty(reportRelationList)) {
            // 找到对应的分摊层级的Id  但是分摊报表里面存的是分摊层级的序号
            List<Long> shareLevelIds = reportRelationList.stream().map(ReportRelation::getRelationCode).map(Long::valueOf).collect(Collectors.toList());
//            List<Integer> levelShortList = costShareLevelList.stream()
//                    .filter(m -> shareLevelIds.contains(m.getId()))
//                    .map(CostShareLevel::getLeverSort).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(shareLevelIds)) {
                // 查询报表里面是当前分摊层级的数据
                List<Allocation> allocations = allocationList.stream().filter(m -> shareLevelIds.contains(m.getShareLevelId()) && m.getTargetResponsibilityCode().equals(i.getResponsibilityCode())).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(allocations)) {
//                    allocations.forEach(m -> {
//                        sum.updateAndGet(v -> v.add(m.getAmount()));
//                    });
                    BigDecimal reduce = allocations.stream().map(Allocation::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                    sum.set(reduce);
                }
            }
        }
//        i.setAmount(new BigDecimal(sum.toString()));
        return sum.get();
    }

    /**
     * 按照责任中心进行计算
     * 原始责任中心是设置的责任中心   目标责任中心是报表的责任中心
     * 查询分摊报表里面目标责任中心是当前责任中心  报表责任中心是当前设置的责任中心
     */
    public BigDecimal setResponsibilityCode(CostDepartmentProfitVO costDepartmentProfitVO, Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList, List<CostDepartmentProfitVO> allList) {
        // 获取当前报表对应的责任中心
        List<ReportRelation> reportRelationList = reportRelationMap.get(costDepartmentProfitVO.getReportId());
        AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.000"));
        if (CollUtil.isNotEmpty(reportRelationList)) {
            // 获取对应的责任中心的Code集合  这个是设置的责任中心
            List<String> responsibilityCodes = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(responsibilityCodes)) {
                // 查询报表里面是当前分摊层级的数据
                List<Allocation> allocations = allocationList.stream().filter(i -> i.getTargetResponsibilityCode().equals(costDepartmentProfitVO.getResponsibilityCode()) && responsibilityCodes.contains(i.getResponsibilityCode())).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(allocations)) {
                    BigDecimal reduce = allocations.stream().map(Allocation::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                    sum.set(reduce);
//                    allocations.forEach(m -> {
//                        sum.updateAndGet(v -> v.add(m.getAmount()));
//                    });
                }
            }
        }
//        costDepartmentProfitVO.setAmount(new BigDecimal(sum.toString()));
        return sum.get();
    }

    /**
     * 按照小计的计算方式
     * 同一个目录下相同的其他金额的和
     */
    public BigDecimal setSubtotal(CostDepartmentProfitVO costDepartmentProfitVO,
                                  List<CostShareLevel> costShareLevelList,
                                  Map<Long, List<CostDepartmentProfitVO>> listMap,
                                  List<CostDepartmentProfitVO> profitVOS,
                                  List<IncomeCollection> list,
                                  List<AllocationQueryReportVO> allocationQueryReportVOList,
                                  Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList, List<CostDepartmentProfitVO> allList) {
        // 因为报表是按照报表项目的升序进行排序的  前面的报表是已经进行计算了的
        // 查询当前报表的父层级id
        Long reportParentId = costDepartmentProfitVO.getReportParentId();
        String responsibilityCode = costDepartmentProfitVO.getResponsibilityCode();
        // 查询报表里面在当前父层级下的并且不是自己的报表项目
        List<CostDepartmentProfitVO> costDepartmentProfitVOS = allList.stream().filter(i -> i.getReportParentId().equals(reportParentId) && i.getResponsibilityCode().equals(responsibilityCode) && !NumberConstant.THREE.equals(i.getCalcType())).collect(Collectors.toList());
        AtomicReference<BigDecimal> sum = new AtomicReference<>(new BigDecimal("0.0000"));
        // 遍历数据 之前的已经经过了计算
        costDepartmentProfitVOS.forEach(i -> {
            Long reportId = i.getReportId();
            List<CostDepartmentProfitVO> costDepartmentProfitVOS1 = listMap.get(reportId);
            if (CollUtil.isEmpty(costDepartmentProfitVOS1)) {
                throw new CostException(500, "报表未找到");
            }
            BigDecimal amount = getAmount(costDepartmentProfitVOS1, costShareLevelList, responsibilityCode, list, allocationQueryReportVOList, reportRelationMap, allocationList, listMap, allList);
            sum.set(amount.add(sum.get()));

        });
//        costDepartmentProfitVO.setAmount(new BigDecimal(sum.toString()));
        return sum.get();
    }

    /***
     * 按照计算方式进行计算
     */
    public BigDecimal setCalculation(CostDepartmentProfitVO costDepartmentProfitVO, List<CostDepartmentProfitVO> costDepartmentProfitVOList,
                                     List<CostShareLevel> costShareLevelList, Map<Long, List<CostDepartmentProfitVO>> listMap,
                                     List<IncomeCollection> list, List<AllocationQueryReportVO> allocationQueryReportVOList,
                                     Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList, List<CostDepartmentProfitVO> allList) {
        // 获取当前报表的计算方式  [1]+[2]类型/ [1]-[2]
        String calcFormula = costDepartmentProfitVO.getCalcFormula();
        String responsibilityCode = costDepartmentProfitVO.getResponsibilityCode();
        String replace = calcFormula.replace("[", "").replace("]", "").replace("+", ",").replace("-", ",-");
        List<Integer> calcFormulaList = Arrays.stream(replace.split(StrUtil.COMMA)).map(Integer::valueOf).collect(Collectors.toList());
        // 查询这个编号集合的报表
        AtomicReference<BigDecimal> bigDecimal = new AtomicReference<>(new BigDecimal("0.0000"));
        calcFormulaList.forEach(calc -> {
            Integer calcNum = Math.abs(calc);
            List<Long> reportIdList = allList.stream().filter(i -> i.getResponsibilityCode().equals(responsibilityCode) && calcNum.equals(i.getReportNum())).map(CostDepartmentProfitVO::getReportId).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(reportIdList)) {
                reportIdList.forEach(i -> {
                    List<CostDepartmentProfitVO> profitVOS = listMap.get(i);
                    if (CollUtil.isEmpty(profitVOS)) {
                        throw new CostException(500, "报表未找到");
                    }
                    BigDecimal amount = getAmount(profitVOS, costShareLevelList, responsibilityCode, list, allocationQueryReportVOList, reportRelationMap, allocationList, listMap, allList);
                    if (calc > 0) {
                        bigDecimal.updateAndGet(v -> v.add(amount));
                    } else {
                        bigDecimal.updateAndGet(v -> v.subtract(amount));
                    }
                });
            }

        });
        return bigDecimal.get();
    }

    /**
     * 判断是那种计算方式 调用方法进行计算
     */
    public BigDecimal getAmount(List<CostDepartmentProfitVO> profitVOS,
                                List<CostShareLevel> costShareLevelList,
                                String responsibilityCode, List<IncomeCollection> list,
                                List<AllocationQueryReportVO> allocationQueryReportVOList,
                                Map<Long, List<ReportRelation>> reportRelationMap, List<Allocation> allocationList,
                                Map<Long, List<CostDepartmentProfitVO>> listMap, List<CostDepartmentProfitVO> allList) {
        BigDecimal bigDecimal = new BigDecimal("0.0000");
        // 在对这个报表进行过滤
        List<CostDepartmentProfitVO> costDepartmentProfitVOS = profitVOS.stream().filter(i -> i.getResponsibilityCode().equals(responsibilityCode)).collect(Collectors.toList());
        // 都一个就是
        CostDepartmentProfitVO costDepartmentProfitVO = costDepartmentProfitVOS.get(0);
        Integer calcType = costDepartmentProfitVO.getCalcType();
        if (NumberConstant.ONE.equals(calcType)) {
            // 调用计算的方法 按照会计科目
            bigDecimal = setAccountReportData(costDepartmentProfitVO, list, allocationQueryReportVOList, reportRelationMap, allList);
        } else if (NumberConstant.TWO.equals(calcType)) {
            // 按照分摊层级
            bigDecimal = setShareLevelReportData(costDepartmentProfitVO, costShareLevelList, reportRelationMap, allocationList, allList);
        } else if (NumberConstant.THREE.equals(calcType)) {
            // 小计
            bigDecimal = setSubtotal(costDepartmentProfitVO, costShareLevelList, listMap, profitVOS, list, allocationQueryReportVOList, reportRelationMap, allocationList, allList);
        } else if (NumberConstant.FIVE.equals(calcType)) {
            // 按照责任中心
            bigDecimal = setResponsibilityCode(costDepartmentProfitVO, reportRelationMap, allocationList, allList);
        } else if (NumberConstant.FOUR.equals(calcType)) {
//            bigDecimal = setCalculation(costDepartmentProfitVO, costDepartmentProfitVOS, costShareLevelList, listMap, list, allocationQueryReportVOList, reportRelationMap, allocationList, allList);
        }
        return bigDecimal;
    }


    private void exportDepartmentProfit(String date, OutputStream outputStream, Integer reportType, String name) throws Exception {

        Long hospId = UserContext.getHospId();
        DateTime dateTime = DateUtil.parse(date);
        int year = DateUtil.year(dateTime);
        int month = DateUtil.month(dateTime) + 1;
        // 查询所有的节点
        List<Responsibility> responsibilityList = responsibilityService.list(new QueryWrapper<Responsibility>().lambda().eq(Responsibility::getHospId, hospId));
        if (CollUtil.isEmpty(responsibilityList)) {
            throw new CostException(500, "责任中心不存在");
        }
        Map<String, Long> responseCodeParentIdMap = new HashMap<>();
        Map<Long, Responsibility> responsibilityIdMap = new HashMap<>();
        Map<String, String> responseCodeNameMap = new HashMap<>();
        Map<String, Long> responseCodeIdMap = new HashMap<>();
        Map<String, Responsibility> responsibilityCodeMap = new HashMap<>();
        Map<String, Integer> responsibilityStatusMap = new HashMap<>();
        Map<String, Integer> responsibilitySortMap = new HashMap<>();
        responsibilityList.forEach(responsibility1 -> {
            responsibilityCodeMap.put(responsibility1.getResponsibilityCode(), responsibility1);
            responseCodeIdMap.put(responsibility1.getResponsibilityCode(), responsibility1.getId());
            responseCodeNameMap.put(responsibility1.getResponsibilityCode(), responsibility1.getResponsibilityName());
            responsibilityIdMap.put(responsibility1.getId(), responsibility1);
            responseCodeParentIdMap.put(responsibility1.getResponsibilityCode(), responsibility1.getParentId());
            responsibilityStatusMap.put(responsibility1.getResponsibilityCode(), responsibility1.getStatus());
            Integer sort = responsibility1.getSort();
            responsibilitySortMap.put(responsibility1.getResponsibilityCode(), sort != null ? sort : Integer.valueOf(1));
        });

        // 损益表数据
        List<CostDepartmentProfit> departmentProfits = this.list(new QueryWrapper<CostDepartmentProfit>().lambda()
                .eq(CostDepartmentProfit::getHospId, hospId)
                .eq(CostDepartmentProfit::getYear, year).eq(CostDepartmentProfit::getMonth, month)
                .eq(CostDepartmentProfit::getShareType, reportType));
        if (CollectionUtils.isEmpty(departmentProfits)) {
            throw new CostException(500, name + "未进行科室损益计算");
        }
        //判断一下责任中心是否停用
        List<CostDepartmentProfit> removeList = new ArrayList<>();
        for (CostDepartmentProfit departmentProfit : departmentProfits) {
            Integer i = responsibilityStatusMap.get(departmentProfit.getResponsibilityCode());
            if (i != null && i == 0) {
                removeList.add(departmentProfit);
            }
            Long aLong = responseCodeParentIdMap.get(departmentProfit.getResponsibilityCode());
            if (aLong != null) {
                if (aLong.equals(NumberConstant.ZERO_L)) {
                    departmentProfit.setParentResponsibilityCode(departmentProfit.getResponsibilityCode());
                    departmentProfit.setParentResponsibilityName(departmentProfit.getResponsibilityName());
                } else {
                    Responsibility responsibility = responsibilityIdMap.get(aLong);
                    if (Objects.nonNull(responsibility)) {
                        departmentProfit.setParentResponsibilityCode(responsibility.getResponsibilityCode());
                        departmentProfit.setParentResponsibilityName(responsibility.getResponsibilityName());
                    }
                }

            }
        }
        //删除停用责任中心数据
        if (!CollectionUtils.isEmpty(removeList)) {
            departmentProfits.removeAll(removeList);
        }
        List<CostDepartmentProfit> profitList = departmentProfits.stream().filter(f -> StringUtils.isEmpty(f.getParentResponsibilityCode())).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(profitList)) {
            log.info("{}报表类型存在无上级责任中心的数据，请核实配置数据", reportType);
        }
        Map<Long, List<CostDepartmentProfit>> profitReportIdGroup = departmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getReportId));
        Map<Long, Map<String, CostDepartmentProfit>> profitReportResponsibilityGroup = new HashMap<>();
        profitReportIdGroup.forEach((k, v) -> {
            profitReportResponsibilityGroup.put(k, v.stream().collect(Collectors.toMap(CostDepartmentProfit::getResponsibilityCode, costDepartmentProfit -> costDepartmentProfit, (a, b) -> b)));
        });
//        Map<String, List<CostDepartmentProfit>> doctorParentMap = departmentProfits.stream().collect(Collectors.groupingBy(CostDepartmentProfit::getParentResponsibilityCode));
        //损益表设置
        List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
                .eq(ReportForm::getHospId, hospId)
                .eq(ReportForm::getReportType, reportType));
        if (CollUtil.isEmpty(reportFormList)) {
            throw new CostException(500, "损益表未找到");
        }
        //第一层
        List<TitleEntity> titleList = new ArrayList<>();
        titleList.add(new TitleEntity("0", null, name, false, NumberConstant.ZERO));
        //从损益数据中提取出所有责任中心组装成树
        List<ResponsibilityVo> responsibilityVos = new ArrayList<>();
        for (CostDepartmentProfit departmentProfit : departmentProfits) {
            Responsibility responsibility = responsibilityCodeMap.get(departmentProfit.getResponsibilityCode());
            ResponsibilityVo responsibilityVo = new ResponsibilityVo();
            responsibilityVo.setParentResponsibilityCode(departmentProfit.getParentResponsibilityCode());
            responsibilityVo.setParentResponsibilityName(departmentProfit.getParentResponsibilityName());
            responsibilityVo.setResponsibilityCode(departmentProfit.getResponsibilityCode());
            responsibilityVo.setResponsibilityName(departmentProfit.getResponsibilityName());
            responsibilityVo.setSort(responsibility.getSort());
            responsibilityVos.add(responsibilityVo);

        }
        ListUtils.sort(responsibilityVos, ResponsibilityVo::getParentResponsibilityName);
        Map<String, List<ResponsibilityVo>> responsibilityMap = responsibilityVos.stream().distinct().collect(Collectors.groupingBy(ResponsibilityVo::getParentResponsibilityCode));
        responsibilityMap.forEach((k, v) -> {
            TitleEntity entity = new TitleEntity();
            entity.setId(String.valueOf(responseCodeIdMap.get(k)));
            entity.setPid("0");
            entity.setContent(responseCodeNameMap.get(k));
            entity.setFieldName(responseCodeNameMap.get(k));
            entity.setWidth(15);
            entity.setSort(responsibilitySortMap.get(k));
            boolean child = getChild(titleList, k, responsibilityMap, responseCodeIdMap, String.valueOf(responseCodeIdMap.get(k)));
            entity.setLast(child);
            titleList.add(entity);
        });


        final List<ReportForm> finalReportFormList = reportFormList;
        List<ReportForm> reportForms = reportFormList.stream().filter(i -> i.getParentId() == 0)
                .peek(i -> i.setChild(this.getReportFormChild(i, finalReportFormList)))
                .collect(Collectors.toList());
        //列
        List<TitleEntity> titleEntities = titleList.stream().filter(TitleEntity::isLast).collect(Collectors.toList());
        List<Map<String, String>> rowList = new ArrayList<>();
        List<Integer> depthList = new ArrayList<>();
        for (ReportForm reportForm : reportForms) {
            int child = TreeDepthUtil.getTreeDepthByDfsWithRecursion(reportForm, "child");
            depthList.add(child);
        }
        OptionalInt max = depthList.stream().mapToInt(Integer::intValue).max();
        //根据报表设置最深深度添加 默认列
        int asInt = max.getAsInt();
        for (int i = 1; i <= asInt; i++) {
            TitleEntity parentResponsibility = new TitleEntity();
            parentResponsibility.setId(String.valueOf(i));
            parentResponsibility.setPid("0");
            parentResponsibility.setContent("");
            parentResponsibility.setFieldName(String.valueOf(i));
            parentResponsibility.setWidth(15);
            parentResponsibility.setSort(NumberConstant.ZERO);
            parentResponsibility.setLast(true);
            titleList.add(parentResponsibility);
        }
        titleList.sort(Comparator.comparing(TitleEntity::getSort));
        DecimalFormat df = new DecimalFormat("0.00%");
        //递归排序
        formSort(reportForms);
        //配置单元格数据
        for (ReportForm reportForm : reportForms) {
            int fieldId = 1;
            Map<String, String> m = new HashMap<String, String>();
            if (!CollectionUtils.isEmpty(reportForm.getChild())) {
                m.put(Integer.toString(fieldId), reportForm.getReportName());
                setRowList(fieldId, reportForm.getChild(), profitReportResponsibilityGroup, rowList, df, titleEntities, m, asInt);
            } else {
                for (int i = 1; i <= asInt; i++) {
                    m.put(Integer.toString(i), reportForm.getReportName());
                }
                Map<String, CostDepartmentProfit> map = profitReportResponsibilityGroup.get(reportForm.getId());
                for (TitleEntity titleEntity : titleEntities) {
                    String fieldName = titleEntity.getFieldName();
                    if (fieldName.contains(AMOUNT_FIELD)) {
                        String[] split1 = StringUtils.split(fieldName, "|");
                        if (split1 != null) {
                            CostDepartmentProfit costDepartmentProfit = map.get(split1[0]);
                            m.put(fieldName, costDepartmentProfit.getAmount().setScale(2, RoundingMode.HALF_UP).toString());

                        } else {
                            m.put(fieldName, "");
                        }
                    } else if (fieldName.contains(PERCENT_FIELD)) {
                        String[] split1 = StringUtils.split(fieldName, "|");
                        if (split1 != null) {
                            CostDepartmentProfit costDepartmentProfit = map.get(split1[0]);
                            if (costDepartmentProfit.getPercent() != null) {
                                m.put(fieldName, df.format(costDepartmentProfit.getPercent()));
                            } else {
                                m.put(fieldName, "");
                            }
                        } else {
                            m.put(fieldName, "");
                        }
                    }

                }
                rowList.add(m);
            }

        }

        //表头树进行excel 元素转换
        ExcelPoiUtil excelTool = new ExcelPoiUtil(name);
        Map<String, String> param = ImmutableMap.<String, String>builder().put("id", "id").put("pid", "pid")
                .put("content", "content").put("fieldName", "fieldName").put("width", "width").build();
        List<ColEntity> titleData = excelTool.colEntityTransformer(titleList, param, "0");

        List<Integer> mergeList = IntStream.range(0, asInt).boxed().collect(Collectors.toList());

        // 多个sheet导出
        XSSFWorkbook workbook = excelTool.exportXssfWorkbook(titleData, rowList, null);
//        CellRangeAddress cellAddresses = new CellRangeAddress(4,7,0,4);
//        workbook.getSheetAt(0).addMergedRegion(cellAddresses);

        //表头占的行数
        int totalRow = titleData.get(0).getTotalRow();
        int[] relationColl = new int[mergeList.size()];
        Map<Integer, int[]> mergeMap = IntStream.range(0, mergeList.size()).boxed().collect(Collectors.toMap(i -> i, i -> relationColl, (a, b) -> b));
        //手动横向合并
        addMergeCells(workbook, mergeMap, asInt);
        //纵向合并
        PoiMergeCellUtil.mergeCells(workbook.getSheetAt(0), mergeMap, totalRow);
//        int[] relationTitleColl = new int[totalRow];
//
//        Map<Integer,int[]> mergeTitleMap = IntStream.range(asInt-1, titleData.get(0).getTotalCol()).boxed().collect(Collectors.toMap(i -> i, i -> relationTitleColl, (a, b) -> b));
//        PoiMergeCellUtil.mergeCells(workbook.getSheetAt(0),mergeTitleMap,1,totalRow-1);

//        excelTool.save(workbook, "D:\\测试用.xlsx");
        workbook.write(outputStream);
        workbook.close();

    }

    private static void addMergeCells(XSSFWorkbook workbook, Map<Integer, int[]> mergeMap, int asInt) {
        XSSFSheet sheet = workbook.getSheetAt(0);
        //最后一行
        Set<Integer> colKeyList = mergeMap.keySet();
        int endRow = sheet.getLastRowNum();
        for (int i = 4; i <= endRow; i++) {
            //mergeMap
            List<String> cellText = new ArrayList<>();
            for (Integer integer : colKeyList) {
                XSSFRow row = sheet.getRow(i);
                String text = PoiCellUtil.getCellValue(row.getCell(integer));
                cellText.add(text);
            }
            // 过滤出元素出现次数大于 1 (重复元素）的 entry
            List<Integer> collect = cellText.stream().filter(j -> !Objects.equals(j, ""))               // list 对应的 Stream 并过滤""
                    .collect(Collectors.toMap(e -> e, e -> 1, Integer::sum)) // 获得元素出现频率的 Map，键为元素，值为元素出现的次数
                    .values()
                    .stream()                       // 所有 entry 对应的 Stream
                    .filter(integer -> integer > 1)                // 获得 entry 的键（重复元素）对应的 Stream
                    .collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(collect)) {
                sheet.addMergedRegion(new CellRangeAddress(i, i, mergeMap.size() - collect.get(0), asInt - 1));
            }
        }
    }

    private void setRowList(int fieldId, List<ReportForm> child, Map<Long, Map<String, CostDepartmentProfit>> profitReportResponsibilityGroup,
                            List<Map<String, String>> rowList, DecimalFormat df, List<TitleEntity> titleEntities,
                            Map<String, String> parentFieldMap, int maxDepth) {
        fieldId++;
        for (ReportForm reportForm : child) {
            Map<String, String> m = new HashMap<String, String>(parentFieldMap);
            m.put(Integer.toString(fieldId), reportForm.getReportName());
            if (!CollectionUtils.isEmpty(reportForm.getChild())) {
                setRowList(fieldId, reportForm.getChild(), profitReportResponsibilityGroup, rowList, df, titleEntities, m, maxDepth);
            } else {
                if (fieldId < maxDepth) {
                    for (int i = 1; i <= maxDepth - fieldId; i++) {
                        m.put(Integer.toString(fieldId + i), reportForm.getReportName());
                    }
                }
                Map<String, CostDepartmentProfit> map = profitReportResponsibilityGroup.get(reportForm.getId());
                for (TitleEntity titleEntity : titleEntities) {
                    String fieldName = titleEntity.getFieldName();
                    if (fieldName.contains(AMOUNT_FIELD)) {
                        String[] split1 = StringUtils.split(fieldName, "|");
                        if (split1 != null) {
                            if (map != null) {
                                CostDepartmentProfit costDepartmentProfit = map.get(split1[0]);
                                if (Objects.nonNull(costDepartmentProfit)) {
                                    m.put(fieldName, costDepartmentProfit.getAmount().setScale(2, RoundingMode.HALF_UP).toString());
                                } else {
                                    m.put(fieldName, "");
                                }
                            } else {
                                m.put(fieldName, "");
                            }


                        } else {
                            m.put(fieldName, "");

                        }
                    } else if (fieldName.contains(PERCENT_FIELD)) {
                        String[] split1 = StringUtils.split(fieldName, "|");
                        if (split1 != null) {
                            if (map != null) {
                                CostDepartmentProfit costDepartmentProfit = map.get(split1[0]);
                                if (costDepartmentProfit.getPercent() != null) {
                                    m.put(fieldName, df.format(costDepartmentProfit.getPercent()));
                                } else {
                                    m.put(fieldName, "");
                                }
                            } else {
                                m.put(fieldName, "");
                            }
                        } else {
                            m.put(fieldName, "");
                        }
                    }
                }
                rowList.add(m);

            }


        }

    }

    private List<ReportForm> getReportFormChild(ReportForm parent, List<ReportForm> reportFormList) {
        return reportFormList.stream().filter(o -> o.getParentId().equals(parent.getId()))
                .peek(o -> o.setChild(this.getReportFormChild(o, reportFormList)))
                .collect(Collectors.toList());
//
    }

    private void formSort(List<ReportForm> reportFormList) {
        for (ReportForm reportForm : reportFormList) {
            if (!CollectionUtils.isEmpty(reportForm.getChild())) {
                formSort(reportForm.getChild());
            }
        }
        reportFormList.sort(Comparator.comparing(ReportForm::getSort));
    }

    private void responsibilitySort(List<Responsibility> responsibilityList) {
        for (Responsibility responsibility : responsibilityList) {
            if (!CollectionUtils.isEmpty(responsibility.getChildren())) {
                responsibilitySort(responsibility.getChildren());
            }
        }
        responsibilityList.sort(Comparator.comparing(Responsibility::getSort, Comparator.nullsLast(Integer::compareTo)));
    }

    private void commonResponsibilityReportVoSort(List<CommonResponsibilityReportVo> T) {
        for (CommonResponsibilityReportVo responsibility : T) {
            if (!CollectionUtils.isEmpty(responsibility.getChild())) {
                commonResponsibilityReportVoSort(responsibility.getChild());
            }
        }
        T.sort(Comparator.comparing(CommonResponsibilityReportVo::getSort, Comparator.nullsLast(Integer::compareTo)));
    }

    private void costResponsibilityProfitVoSort(List<CostResponsibilityProfitVo> T) {
        for (CostResponsibilityProfitVo responsibility : T) {
            if (!CollectionUtils.isEmpty(responsibility.getChild())) {
                costResponsibilityProfitVoSort(responsibility.getChild());
            }
        }
        T.sort(Comparator.comparing(CostResponsibilityProfitVo::getSort, Comparator.nullsLast(Integer::compareTo)));
    }

    @Override
    public Object getBatchComputeProfitListByYear(String startYear, String endYear, String reportType, String responsibilityCode) {
        Integer integerReportType = Integer.valueOf(reportType);
        Long hospId = UserContext.getHospId();
        List<BatchCostProfitResponse> responses = new ArrayList<>();
        // 解析起止年份
        int startY = Integer.parseInt(startYear);
        int endY = Integer.parseInt(endYear);

        if (startY > endY) {
            throw new CostException(500, "起始年份不能大于结束年份");
        }
        // 获取报表配置
        List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
                .eq(ReportForm::getHospId, hospId)
                .eq(ReportForm::getDeleteTime, NumberConstant.ZERO)
                .eq(ReportForm::getReportType, integerReportType));
        if (CollUtil.isEmpty(reportFormList)) {
            throw new CostException(500, "损益表未找到");
        }
        Map<Long, ReportForm> reportMap = reportFormList.stream()
                .collect(Collectors.toMap(ReportForm::getId, report -> report));
        // 取非隐藏的报表项目ID
        List<Long> activeReportIdList = reportFormList.stream()
                .filter(report -> NumberConstant.ONE.equals(report.getHide()))
                .map(ReportForm::getId)
                .collect(Collectors.toList());

        // 获取当前年份和上一年度的汇总数据（一次性查询）
        List<CostProfitVo> summaryList = this.baseMapper.getAnnualSummaryByYearRange(startY, endY, hospId, integerReportType, responsibilityCode);
        List<CostProfitVo> preYearSummaryList = this.baseMapper.getAnnualSummaryByYearRange(startY - 1, endY - 1, hospId, integerReportType, responsibilityCode);

        // 按年份分组处理数据
        Map<Integer, List<CostProfitVo>> currentYearMap = new HashMap<>();
        Map<Integer, List<CostProfitVo>> preYearMap = new HashMap<>();

        // 将结果按年份分组
        if (!CollectionUtils.isEmpty(summaryList)) {
            currentYearMap = summaryList.stream()
                    .collect(Collectors.groupingBy(CostProfitVo::getYear));
        }

        if (!CollectionUtils.isEmpty(preYearSummaryList)) {
            preYearMap = preYearSummaryList.stream()
                    .collect(Collectors.groupingBy(CostProfitVo::getYear));
        }

        // 遍历每个年份进行数据处理
        for (int year = startY; year <= endY; year++) {
            int previousYear = year - 1;

            List<CostProfitVo> currentYearList = currentYearMap.get(year);
            List<CostProfitVo> previousYearList = preYearMap.get(previousYear);

            if (CollectionUtils.isEmpty(currentYearList)) {
                continue;
            }

            // 只处理非隐藏的项目
            List<CostProfitVo> activeCostProfitVo = currentYearList.stream()
                    .filter(vo -> activeReportIdList.contains(vo.getReportId()))
                    .collect(Collectors.toList());
            if (CollectionUtils.isEmpty(activeCostProfitVo)) {
                continue;
            }

            // 创建映射以便快速查找上一年的数据
            Map<Long, CostProfitVo> preYearCostProfitMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(previousYearList)) {
                preYearCostProfitMap = previousYearList.stream()
                        .collect(Collectors.toMap(CostProfitVo::getReportId, costProfitVo -> costProfitVo));
            }

            // 计算完成率、环比、同比
            for (CostProfitVo vo : activeCostProfitVo) {
                // 设置同期数据
                if (preYearCostProfitMap.containsKey(vo.getReportId())) {
                    vo.setSamePeriodAmount(preYearCostProfitMap.get(vo.getReportId()).getAmount());
                } else {
                    vo.setSamePeriodAmount(BigDecimal.ZERO);
                }

                vo.setCompletionRate(calculateRate(vo.getAmount(), vo.getBudgetAmount()));
                vo.setMomRate(calculateRate(vo.getAmount().subtract(vo.getPrevPeriodAmount()), vo.getPrevPeriodAmount()));
                vo.setYoyRate(calculateRate(vo.getAmount().subtract(vo.getSamePeriodAmount()), vo.getSamePeriodAmount()));

                // 设置报表相关属性
                ReportForm reportForm = reportMap.get(vo.getReportId());
                if (reportForm != null) {
                    vo.setDescription(reportForm.getDescription());
                    vo.setSort(reportForm.getSort());
                    vo.setPermil(reportForm.getPermil());
                    vo.setDataType(reportForm.getDataType());
                    vo.setDecimalPlace(reportForm.getDecimalPlace());
                    vo.setFontColor(reportForm.getFontColor());
                }
            }

            // 构建树状结构
            Map<Long, List<CostProfitVo>> collect = activeCostProfitVo.stream()
                    .collect(Collectors.groupingBy(CostProfitVo::getReportParentId));
            List<CostProfitVo> costProfitParentVos = collect.get(NumberConstant.ZERO_L);
            collect.remove(NumberConstant.ZERO_L);

            if (!CollectionUtils.isEmpty(costProfitParentVos)) {
                costProfitParentVos.forEach(parentVo -> {
                    parentVo.setChildren(collect.get(parentVo.getReportId()));
                });
                costProfitParentVos.sort(Comparator.comparing(CostProfitVo::getSort, Comparator.nullsLast(Integer::compareTo)));
            }

            BatchCostProfitResponse response = new BatchCostProfitResponse();
            response.setComputeDate(String.valueOf(year));
            response.setProfitVoList(costProfitParentVos);
            response.setAllowDrillDown(false);
            responses.add(response);
        }

        return responses;
    }


    /**
     * 安全地计算百分比：避免除零错误
     */
    private BigDecimal calculateRate(BigDecimal current, BigDecimal base) {
        if (base == null || base.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }
        BigDecimal rate = current.divide(base, 4, RoundingMode.HALF_UP);
        return rate.setScale(4, RoundingMode.HALF_UP);
    }

    /**
     * 计算科室损益
     * @param computeDate
     * @param hospId
     * @param reportType
     */
    private void calcDeptProfit(String computeDate, Long hospId, String reportType) {
        //获取科室损益计算所需的数据
        ProfitCalculationDataVo profitCalculationData = getProfitCalculationData(computeDate, hospId, reportType);
        //计算科室损益
        List<CostDepartmentProfitVO> costDepartmentProfitVOS = calcDeptProfit(profitCalculationData);
        // 添加数据
        List<CostDepartmentProfit> costDepartmentProfits = BeanUtil.convertList(costDepartmentProfitVOS, CostDepartmentProfit.class);
        //统一创建时间
        long l = System.currentTimeMillis();
        costDepartmentProfits.forEach(i -> {
            i.setCreateTime(l);
        });
        // 删除这个年月的数据
        deleteDeptProfit(profitCalculationData.getYear(),profitCalculationData.getMonth(),reportType ,hospId);
        costDepartmentProfitAccountRepository.deleteDeptProfitAccountWithUser(hospId,computeDate,profitCalculationData.getCurrentUserID());
        //保存科室损益数据
        this.batchInsert(costDepartmentProfits);
        //处理科室损益的会计科目金额数据
        List<CostDepartmentProfitAccount> costDepartmentProfitAccounts=new ArrayList<>();
        for (CostDepartmentProfit deptProfit : costDepartmentProfits) {
            deptProfit.getCostDepartmentProfitAccounts().forEach(account -> {
                account.setDeptProfitId(deptProfit.getId());
                account.setComputeDate(computeDate);
                account.setHospId(hospId);
            });
            costDepartmentProfitAccounts.addAll(deptProfit.getCostDepartmentProfitAccounts());
        }
        //保存科室损益的会计科目金额数据
        costDepartmentProfitAccountRepository.batchInsert(costDepartmentProfitAccounts);
        //记录最后一次 损益计算日期
        computeLastProfitDateRepository.saveLastComputeDate(hospId, computeDate,profitCalculationData.getCurrentUserID());
    }

    /**
     * 获取科室损益计算所需的数据
     * @param computeDate
     * @param hospId
     * @param reportType
     * @return
     */
    public ProfitCalculationDataVo getProfitCalculationData(String computeDate, Long hospId, String reportType) {
        ProfitCalculationDataVo profitCalculationData = new ProfitCalculationDataVo();
        profitCalculationData.setCurrentUserID(UserContext.getCurrentUser().getId());
        Integer year = ComputeDateUtils.getComputeYear(computeDate);
        Integer month = ComputeDateUtils.getComputeMonth(computeDate);

        // 获取指定类型的报表配置
        List<ReportForm> reportFormList = getReportForm(reportType);
        if (CollUtil.isEmpty(reportFormList)) {
            throw new CostException(500, "损益表未找到");
        }
        //获取报表设置明细
        List<ReportRelation> reportRelation = getReportRelation();
        Map<Long, List<ReportRelation>> reportRelationMap = reportRelation.stream().collect(Collectors.groupingBy(ReportRelation::getReportId));

        // 查询最后一个层级的责任中心
        List<CostShareLevel> costShareLevelList = getCostShareLevelList();
        if (CollUtil.isEmpty(costShareLevelList)) {
            throw new CostException(500, "分摊层级未设置");
        }

        //获取指定报表对应的责任中心
        List<Responsibility> responsibilityList = getReportResponsibilityList(reportType);

        // 获取归集后的收入数据
        List<IncomeCollection> incomeList = getIncomeCollectionList(year,month);
        if (CollUtil.isEmpty(incomeList)) {
            throw new CostException(500, "归集后数据不存在");
        }
        Map<String, Map<String, List<IncomeCollection>>> respIncomeGroup = incomeList.stream()
                .collect(Collectors.groupingBy(
                        IncomeCollection::getResponsibilityCode,
                        Collectors.groupingBy(IncomeCollection::getAccountingCode)
                ));


        // 获取分摊后数据
        List<AllocationQuery> allocationQueryList = allocationQueryService.getAllByDate(hospId,year,month);
        if (CollUtil.isEmpty(allocationQueryList)) {
            throw new CostException(500, "分摊后数据不存在");
        }

        DictDataVo accountingTypeDict = centerService.getDict(Constant.ACCOUNTING_TYPE);
        DictDataVo costTypeDict = centerService.getDict(Constant.STANDARD_COST_CATEGORIES);
        List<Accounting> allCostAccounting = accountingRepository.getAllCostAccounting();

        // 创建一个映射，用于快速查找会计科目的类型，过滤掉 null 对象，过滤掉 accountingCode 为 null 的对象
        Map<String, Accounting> accountingMap = allCostAccounting.stream()
                .filter(Objects::nonNull)
                .filter(a -> a.getAccountingCode() != null)
                .collect(Collectors.toMap(Accounting::getAccountingCode, o -> o));

        List<DictDataVo> accountingTypeDictList = (accountingTypeDict != null && accountingTypeDict.getDataVoList() != null)
                ? accountingTypeDict.getDataVoList() : new ArrayList<>();

        List<DictDataVo> costTypeDictList = (costTypeDict != null && costTypeDict.getDataVoList() != null)
                ? costTypeDict.getDataVoList() : new ArrayList<>();

        // 创建一个映射，用于快速查找会计科目类型的扩展字段，过滤掉 null 对象，过滤掉 code 为 null 的对象
        Map<String, DictDataVo> accountingTypeMap = accountingTypeDictList.stream()
                .filter(Objects::nonNull)
                .filter(d -> d.getCode() != null)
                .collect(Collectors.toMap(DictDataVo::getCode, o -> o));

        // 创建一个映射，用于快速查找会计科目类型的扩展字段，过滤掉 null 对象，过滤掉 code 为 null 的对象
        Map<String, DictDataVo> costTypeMap = costTypeDictList.stream()
                .filter(Objects::nonNull)
                .filter(d -> d.getCode() != null)
                .collect(Collectors.toMap(DictDataVo::getCode, o -> o));

        // 封装数据
        List<AllocationQueryReportVO> allocationQueryReportVOList = BeanUtil.convertList(allocationQueryList, AllocationQueryReportVO.class);
        allocationQueryReportVOList.forEach(i -> {
            i.setAccountingCodes(Arrays.asList(i.getAccountingCode().split(StrUtil.COMMA)));
            i.setAccountingNames(Arrays.asList(i.getAccountingName().split(StrUtil.COMMA)));
            //构建会计科目的成本类型及会计科目类型
            Accounting accounting = accountingMap.get(i.getAccountingCode());
            if(ObjectUtils.isEmpty( accounting)){
                return;
            }
            DictDataVo costType = costTypeMap.get(String.valueOf(accounting.getCostType()));
            if(!ObjectUtils.isEmpty( costType)){
                i.setCostType(costType.getExpandOne());
            }
            DictDataVo accountingType = accountingTypeMap.get(String.valueOf(accounting.getCostType()));
            if(!ObjectUtils.isEmpty( accountingType)){
                i.setAccountType(accountingType.getExpandOne());
            }
        });

        //责任中心+会计科目分组
        Map<String, Map<String, List<AllocationQueryReportVO>>> respAccountCostGroup = allocationQueryReportVOList.stream()
                .collect(Collectors.groupingBy(
                        AllocationQueryReportVO::getTargetResponsibilityCode,
                        Collectors.groupingBy(AllocationQueryReportVO::getAccountingCode)
                ));

        //责任中心+来源责任中心分组
        Map<String, Map<String, List<AllocationQueryReportVO>>> respSourceCostGroup = allocationQueryReportVOList.stream()
                .collect(Collectors.groupingBy(
                        AllocationQueryReportVO::getTargetResponsibilityCode,
                        Collectors.groupingBy(AllocationQueryReportVO::getResponsibilityCode)
                ));
        //责任中心+分摊层级分组
        Map<String, Map<Long, List<AllocationQueryReportVO>>> respShareLevelCostGroup = allocationQueryReportVOList.stream()
                .collect(Collectors.groupingBy(
                        AllocationQueryReportVO::getTargetResponsibilityCode,
                        Collectors.groupingBy(AllocationQueryReportVO::getShareLevelId)
                ));

        // 查询分摊的报表数据 后面的计算方式需要使用 小计等需要使用
        List<Allocation> allocationList = allocationService.getByDate( year, month, hospId);
        if (CollUtil.isEmpty(allocationList)) {
            throw new CostException(500, "分摊报表数据不存在");
        }
        profitCalculationData.setComputeDate(computeDate);
        profitCalculationData.setYear(year);
        profitCalculationData.setMonth(month);
        profitCalculationData.setHospId(hospId);
        profitCalculationData.setReportType(reportType);
        profitCalculationData.setReportFormList(reportFormList);
        profitCalculationData.setReportRelationList(reportRelation);
        profitCalculationData.setReportRelationMap(reportRelationMap);
        profitCalculationData.setCostShareLevelList(costShareLevelList);
        profitCalculationData.setResponsibilityList(responsibilityList);
        profitCalculationData.setRespIncomeGroup(respIncomeGroup);
        profitCalculationData.setRespAccountCostGroup(respAccountCostGroup);
        profitCalculationData.setRespSourceCostGroup(respSourceCostGroup);
        profitCalculationData.setRespShareLevelCostGroup(respShareLevelCostGroup);
        return profitCalculationData;
    }

    /**
     * 计算科室损益
     * @param profitCalculationData
     * @return
     */
    private List<CostDepartmentProfitVO> calcDeptProfit(ProfitCalculationDataVo profitCalculationData) {
        List<ReportForm> firstLevelReports = profitCalculationData.getReportFormList().stream().filter(i -> NumberConstant.ZERO.equals(i.getParentId().intValue())).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(firstLevelReports)){
            throw new CostException(500, "未找到第一层报表项目，请检查报表配置");
        }
        //按顺序号排序
        firstLevelReports.sort(Comparator.comparing(ReportForm::getSort, Comparator.nullsLast(Integer::compareTo)));
        Map<Long, List<ReportForm>> reportParentGroup = profitCalculationData.getReportFormList().stream().collect(Collectors.groupingBy(ReportForm::getParentId));
        List<CostDepartmentProfitVO> costDepartmentProfitVOList = new ArrayList<>();
        //循环设置子级报表项目
        for (ReportForm reportForm : firstLevelReports) {
            setChildReport(reportForm,reportParentGroup);
        }
        //虚拟一个最上层的节点方便循环嵌套计算
        ReportForm baseReport=new ReportForm();
        baseReport.setId(NumberConstant.ZERO_L);
        baseReport.setChild(firstLevelReports);
        //按责任中心计算科室损益
//        for (Responsibility responsibility : profitCalculationData.getResponsibilityList()) {
//            Map<Integer,CostDepartmentProfitVO> costDepartmentProfitMap=new HashMap<>();
//            //计算责任中心的所有报表项目
//            for (ReportForm reportForm : firstLevelReports) {
//                calcRespReportAmount(responsibility, reportForm,profitCalculationData, costDepartmentProfitMap);
//            }
//            //添加到结果集合
//            costDepartmentProfitVOList.addAll(costDepartmentProfitMap.values());
//        }
        //按责任中心计算科室损益（并行）
        List<CostDepartmentProfitVO> result = profitCalculationData.getResponsibilityList().parallelStream()
                .map(responsibility -> {
                    Map<Integer, CostDepartmentProfitVO> costDepartmentProfitMap = new HashMap<>();
                    // 计算责任中心的所有报表项目
                    calcRespReportAmount(responsibility, baseReport, profitCalculationData, costDepartmentProfitMap);
                    return new ArrayList<>(costDepartmentProfitMap.values());
                })
                .flatMap(List::stream)
                .collect(Collectors.toList());

        costDepartmentProfitVOList.addAll(result);
        return costDepartmentProfitVOList;
    }

    /**
     * 循环设置子级报表项目
     * @param reportForm
     * @param reportParentGroup
     */
    public void setChildReport(ReportForm reportForm ,Map<Long, List<ReportForm>> reportParentGroup){
        List<ReportForm> childReportForms = reportParentGroup.get(reportForm.getId());
        if(CollUtil.isEmpty(childReportForms)){
            return;
        }
        reportForm.setChild(childReportForms);
        for (ReportForm cildReportForm : childReportForms) {
            setChildReport(cildReportForm,reportParentGroup);
        }
    }


    /**
     * 计算指定责任中心指定报表项目的金额（优先计算子级，再按顺序号计算非公式项，最后计算公式项）
     * @param profitCalculationData
     * @param costDepartmentProfitMap
     * @param parentReport
     * @param responsibility
     */
    public void calcRespReportAmount(Responsibility responsibility,
                                 ReportForm parentReport ,
                                 ProfitCalculationDataVo profitCalculationData,
                                 Map<Integer,CostDepartmentProfitVO> costDepartmentProfitMap){
        //有子级的优先计算子级
        if(!CollUtil.isEmpty(parentReport.getChild())){
            //计算报表项目的金额
            for (ReportForm reportForm : parentReport.getChild()) {
                //计算子级的金额
                calcRespReportAmount(responsibility,reportForm,profitCalculationData,costDepartmentProfitMap);
            }
            //找出所有类型不是计算公式且不是不设置的报表项
            List<ReportForm> calcReportList = parentReport.getChild().stream().filter(i ->!NumberConstant.ZERO.equals(i.getCalcType())&& !NumberConstant.THREE.equals(i.getCalcType())).collect(Collectors.toList());
            //优先计算类型为非计算公式的报表项
            if (!CollUtil.isEmpty(calcReportList)){
                for (ReportForm reportForm : calcReportList) {
                    calcReportAmount(responsibility,reportForm,profitCalculationData,costDepartmentProfitMap);
                }
            }
            //找出所有类型为计算公式的报表项
            List<ReportForm> formulaReportList = parentReport.getChild().stream().filter(i -> NumberConstant.THREE.equals(i.getCalcType())).collect(Collectors.toList());
            //再计算类型为计算公式的报表项
            if (!CollUtil.isEmpty(formulaReportList)){
                for (ReportForm reportForm : formulaReportList) {
                    calcReportAmount(responsibility,reportForm,profitCalculationData,costDepartmentProfitMap);
                }
            }
        }
        //虚拟的最上层不需要计算
        if(!NumberConstant.ZERO_L.equals(parentReport.getId())) {
            //再计算自己
            calcReportAmount(responsibility, parentReport, profitCalculationData, costDepartmentProfitMap);
        }
    }


    /**
     * 计算一个报表项目的金额
     * @param profitCalculationData
     * @param costDepartmentProfitMap
     * @param reportForm
     */
    public void calcReportAmount(Responsibility responsibility,ReportForm reportForm,ProfitCalculationDataVo profitCalculationData,Map<Integer,CostDepartmentProfitVO> costDepartmentProfitMap){
        Integer calcType = reportForm.getCalcType();
        CostDepartmentProfitVO costDepartmentProfitVO = createCostDepartmentProfitVO(responsibility,reportForm,profitCalculationData);
        switch (calcType){
            case 1:
                if(NumberConstant.ONE.equals(reportForm.getCostType())){
                    //按收入会计科目计算
                    setIncomeAccountReportValue(costDepartmentProfitVO,profitCalculationData,responsibility,reportForm);
                }else{
                    //按成本会计科目计算
                    setCostAccountReportValue(costDepartmentProfitVO,profitCalculationData, responsibility, reportForm);
                }
                break;
            case 2:
                //按分摊层级计算
                setShareLevelReportValue(costDepartmentProfitVO,profitCalculationData,responsibility,reportForm);
                break;
            case 4:
                //按公式计算
                setFormulaReportValue(costDepartmentProfitVO,costDepartmentProfitMap,responsibility,reportForm);
                break;
            case 5:
                //按责任中心计算
                setResponsibilityReportValue(costDepartmentProfitVO,profitCalculationData,costDepartmentProfitMap,responsibility,reportForm);
                break;
        }
        //记录下已计算好的报表项目
        if(!costDepartmentProfitMap.containsKey(reportForm.getNum())){
            costDepartmentProfitMap.put(reportForm.getNum(),costDepartmentProfitVO);
        }
    }

    /**
     * 创建一个科室损益计算结果对象
     * @param responsibility
     * @param reportForm
     * @param profitCalculationData
     * @return
     */
    public CostDepartmentProfitVO createCostDepartmentProfitVO(Responsibility responsibility,ReportForm reportForm,ProfitCalculationDataVo profitCalculationData){
        CostDepartmentProfitVO costDepartmentProfitVO = new CostDepartmentProfitVO();
        costDepartmentProfitVO.setYear(profitCalculationData.getYear());
        costDepartmentProfitVO.setMonth(profitCalculationData.getMonth());
        costDepartmentProfitVO.setReportId(reportForm.getId());
        costDepartmentProfitVO.setReportNum(reportForm.getNum());
        costDepartmentProfitVO.setCalcType(reportForm.getCalcType());
        costDepartmentProfitVO.setReportName(reportForm.getReportName());
        costDepartmentProfitVO.setCalcFormula(reportForm.getCalcFormula());
        costDepartmentProfitVO.setReportParentId(reportForm.getParentId());
        costDepartmentProfitVO.setResponsibilityCode(responsibility.getResponsibilityCode());
        costDepartmentProfitVO.setResponsibilityName(responsibility.getResponsibilityName());
        costDepartmentProfitVO.setCostType(NumberConstant.ONE);
        costDepartmentProfitVO.setIncomeType(NumberConstant.ONE);
        costDepartmentProfitVO.setHospId(profitCalculationData.getHospId());
        costDepartmentProfitVO.setShareType(Integer.valueOf(profitCalculationData.getReportType()));
        costDepartmentProfitVO.setType(reportForm.getCostType());
        costDepartmentProfitVO.setFraction(reportForm.getFraction());
        costDepartmentProfitVO.setAmount(BigDecimal.ZERO);
        costDepartmentProfitVO.setCostDepartmentProfitAccounts(new ArrayList<>());
        return costDepartmentProfitVO;
    }

    /**
     * 获取按责任中心计算结果
     * @param profitCalculationData
     * @param costDepartmentProfitMap
     * @param reportForm
     * @return
     */
    private void setResponsibilityReportValue(CostDepartmentProfitVO costDepartmentProfitVO, ProfitCalculationDataVo profitCalculationData, Map<Integer, CostDepartmentProfitVO> costDepartmentProfitMap, Responsibility responsibility, ReportForm reportForm) {
        List<ReportRelation> reportRelationList = profitCalculationData.getReportRelationMap().get(reportForm.getId());
        if(CollectionUtils.isEmpty(reportRelationList)){
            return ;
        }
        // 获取对应的会计科目信息  筛选会计科目的Code
        List<String> responsibilityCodeList = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList());
        // 获取指定责任中心的分摊数据
        Map<String, List<AllocationQueryReportVO>> respSourceCostMap = profitCalculationData.getRespSourceCostGroup().get(responsibility.getResponsibilityCode());
        if(ObjectUtils.isEmpty(respSourceCostMap) || respSourceCostMap.isEmpty()){
            return ;
        }
        //获取指定会计科目的分摊数据
        List<AllocationQueryReportVO> reportVOList=new ArrayList<>();
        responsibilityCodeList.forEach(respCode -> {
            if(respSourceCostMap.containsKey(respCode)){
                reportVOList.addAll(respSourceCostMap.get(respCode));
            }
        });
        if(CollectionUtils.isEmpty(reportVOList)){
            return ;
        }
        List<CostDepartmentProfitAccount> costDepartmentProfitAccounts = calculateCostByTypeAndAccount(reportVOList);
        BigDecimal totalAmount = costDepartmentProfitAccounts.stream()
                .map(CostDepartmentProfitAccount::getAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        costDepartmentProfitVO.setAmount(totalAmount);
        costDepartmentProfitVO.setCostDepartmentProfitAccounts(costDepartmentProfitAccounts);
    }

    /**
     * 获取按公式计算结果
     * @param responsibility
     * @param costDepartmentProfitMap
     * @param reportForm
     * @return
     */
    private void setFormulaReportValue(CostDepartmentProfitVO costDepartmentProfitVO,Map<Integer, CostDepartmentProfitVO> costDepartmentProfitMap,Responsibility responsibility, ReportForm reportForm) {
        // 获取当前报表的计算方式  [1]+[2]类型/ [1]-[2] [1]*[2] [1]/[2]
        String formula = reportForm.getCalcFormula();
        if (StrUtil.isBlank(formula)) {
            costDepartmentProfitVO.setAmount(BigDecimal.ZERO);
            costDepartmentProfitVO.setCostDepartmentProfitAccounts(new ArrayList<>());
            return ;
        }

        String responsibilityCode = responsibility.getResponsibilityCode();

        // 找出公式当中所有代码
        String replace = formula.replace("[", "")
                .replace("]", "")
                .replace("-", ",")
                .replace("+", ",")
                .replace("*", ",")
                .replace("/", ",");

        ArrayList<String> codeList = CollUtil.newArrayList(replace.split(","));
        Map<Integer, String> codeMap = new ConcurrentHashMap<>();
        for (int j = 0; j < codeList.size(); j++) {
            codeMap.put(j, codeList.get(j));
        }

        List<String> expressions = ReUtil.findAll("[^0-9]", "+" + formula.replace("[", "")
                        .replace("]", "").trim(), 0)
                .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());

        // 得到预算表达式 得到所有表达式的Map  +  -  *  / 相关的
        Map<Integer, String> expressionMap = new ConcurrentHashMap<>();
        for (int k = 0; k < expressions.size(); k++) {
            expressionMap.put(k, expressions.get(k));
        }

        // 数字的索引和表达式的索引累加计算
        Set<Integer> codeSet = codeMap.keySet();
        List<Integer> codes = new ArrayList<>(codeSet);
        AtomicReference<BigDecimal> totalAmount = new AtomicReference<>(BigDecimal.ZERO);
        List<CostDepartmentProfitAccount> baseDeptProfitAccounts=new ArrayList<>();
        for (int i = 0; i < codes.size(); i++) {
            // 编号
            String code = codeMap.get(i);
            CostDepartmentProfitVO reportData = costDepartmentProfitMap.get(Integer.valueOf(code));

            // 检查报表数据是否存在且属于当前责任中心
            if (reportData == null || !responsibilityCode.equals(reportData.getResponsibilityCode())) {
                continue;
            }

            BigDecimal amount = reportData.getAmount();
            if (amount == null) {
                amount = BigDecimal.ZERO;
            }

            String str = expressionMap.get(i);
            if (str.equals("+")) {
                baseDeptProfitAccounts=calculateAccountAmounts(baseDeptProfitAccounts,reportData.getCostDepartmentProfitAccounts(),NumberConstant.ONE);
                totalAmount.set(totalAmount.get().add(amount));
            } else if (str.contains("-")) {
                baseDeptProfitAccounts=calculateAccountAmounts(baseDeptProfitAccounts,reportData.getCostDepartmentProfitAccounts(),NumberConstant.NEGATIVE);
                totalAmount.set(totalAmount.get().subtract(amount));
            } else if (str.contains("*")) {
                totalAmount.set(totalAmount.get().multiply(amount));
            } else if (str.contains("/")) {
                if (amount.compareTo(BigDecimal.ZERO) == 0) {
                    log.error("报表项【" + reportForm.getReportName() + "】公式除数为0，报表编号为【" + code + "】");
                    totalAmount.set(BigDecimal.ZERO);
                    break;
                } else {
                    totalAmount.set(totalAmount.get().divide(amount, 6, RoundingMode.HALF_UP));
                }
            }
        }
        //有乘除算法的只要赋值，不用设置会计科目金额
        if(formula.contains("*")||formula.contains("/")){
            costDepartmentProfitVO.setAmount(totalAmount.get());
            costDepartmentProfitVO.setCostDepartmentProfitAccounts(new ArrayList<>());
        }else{
            costDepartmentProfitVO.setAmount(totalAmount.get());
            costDepartmentProfitVO.setCostDepartmentProfitAccounts(baseDeptProfitAccounts);
        }

    }

    /**
     * 对两个CostDepartmentProfitVO对象的costDepartmentProfitAccounts列表进行加减运算
     * 按照相同的costType和accountType进行合并计算，只处理amount字段
     *
     * @param firstList 第一个CostDepartmentProfitVO对象
     * @param secondList 第二个CostDepartmentProfitVO对象
     * @param operation 运算符，1表示加法，-1表示减法
     * @return 运算结果列表
     */
    public List<CostDepartmentProfitAccount> calculateAccountAmounts(
            List<CostDepartmentProfitAccount> firstList,
            List<CostDepartmentProfitAccount> secondList,
            int operation) {

        // 处理空列表情况
        firstList = firstList != null ?firstList : new ArrayList<>();
        secondList = secondList != null ?secondList: new ArrayList<>();

        // 创建结果列表，先复制第一个列表的所有元素
        List<CostDepartmentProfitAccount> result = firstList.stream()
                .map(account -> {
                    CostDepartmentProfitAccount copy = new CostDepartmentProfitAccount();
                    copy.setCostType(account.getCostType());
                    copy.setAccountType(account.getAccountType());
                    copy.setAmount(account.getAmount() != null ? account.getAmount() : BigDecimal.ZERO);
                    return copy;
                })
                .collect(Collectors.toList());

        // 处理第二个列表中的每个元素
        for (CostDepartmentProfitAccount secondAccount : secondList) {
            if (secondAccount.getAmount() == null) {
                continue; // 跳过金额为空的记录
            }

            // 查找是否在结果列表中已有相同costType和accountType的记录
            boolean found = false;
            for (CostDepartmentProfitAccount resultAccount : result) {
                if (Objects.equals(resultAccount.getCostType(), secondAccount.getCostType()) &&
                        Objects.equals(resultAccount.getAccountType(), secondAccount.getAccountType())) {

                    // 找到匹配项，进行加减运算
                    BigDecimal firstAmount = resultAccount.getAmount() != null ? resultAccount.getAmount() : BigDecimal.ZERO;
                    BigDecimal secondAmount = secondAccount.getAmount() != null ? secondAccount.getAmount() : BigDecimal.ZERO;

                    if (operation == 1) {
                        resultAccount.setAmount(firstAmount.add(secondAmount));
                    } else if (operation == -1) {
                        resultAccount.setAmount(firstAmount.subtract(secondAmount));
                    }

                    found = true;
                    break;
                }
            }

            // 如果未找到匹配项，则添加新记录
            if (!found) {
                CostDepartmentProfitAccount newAccount = new CostDepartmentProfitAccount();
                newAccount.setCostType(secondAccount.getCostType());
                newAccount.setAccountType(secondAccount.getAccountType());

                // 加法直接添加金额，减法添加负金额
                if (operation == 1) {
                    newAccount.setAmount(secondAccount.getAmount() != null ? secondAccount.getAmount() : BigDecimal.ZERO);
                } else if (operation == -1) {
                    BigDecimal amount = secondAccount.getAmount() != null ? secondAccount.getAmount() : BigDecimal.ZERO;
                    newAccount.setAmount(amount.negate()); // 设置为负值
                }
                result.add(newAccount);
            }
        }

        return result;
    }


    /**
     * 获取按分摊层级计算结果
     * @param profitCalculationData
     * @param reportForm
     * @return
     */
    private void setShareLevelReportValue(CostDepartmentProfitVO costDepartmentProfitVO, ProfitCalculationDataVo profitCalculationData, Responsibility responsibility, ReportForm reportForm) {
        List<ReportRelation> reportRelationList = profitCalculationData.getReportRelationMap().get(reportForm.getId());
        if(CollectionUtils.isEmpty(reportRelationList)){
            return ;
        }
        // 获取对应的会计科目信息  筛选会计科目的Code
        List<Long> shareLevelIdList = reportRelationList.stream().map(o->Long.valueOf(o.getRelationCode())).collect(Collectors.toList());
        // 获取指定责任中心的分摊数据
        Map<Long, List<AllocationQueryReportVO>> respShareLevelCostMap = profitCalculationData.getRespShareLevelCostGroup().get(responsibility.getResponsibilityCode());
        if(ObjectUtils.isEmpty(respShareLevelCostMap) || respShareLevelCostMap.isEmpty()){
            return ;
        }
        //获取指定会计科目的分摊数据
        List<AllocationQueryReportVO> reportVOList=new ArrayList<>();
        shareLevelIdList.forEach(shareLevelId -> {
            if(respShareLevelCostMap.containsKey(shareLevelId)){
                reportVOList.addAll(respShareLevelCostMap.get(shareLevelId));
            }
        });
        if(CollectionUtils.isEmpty(reportVOList)){
            return ;
        }
        List<CostDepartmentProfitAccount> costDepartmentProfitAccounts = calculateCostByTypeAndAccount(reportVOList);
        BigDecimal totalAmount = costDepartmentProfitAccounts.stream()
                .map(CostDepartmentProfitAccount::getAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        costDepartmentProfitVO.setAmount(totalAmount);
        costDepartmentProfitVO.setCostDepartmentProfitAccounts(costDepartmentProfitAccounts);
    }


    /**
     * 按收入会计科目计算
     * @param costDepartmentProfitVO
     * @param profitCalculationData
     * @param responsibility
     * @param reportForm
     */
    private void setIncomeAccountReportValue(CostDepartmentProfitVO costDepartmentProfitVO,ProfitCalculationDataVo profitCalculationData, Responsibility responsibility,ReportForm reportForm) {
        List<ReportRelation> reportRelationList = profitCalculationData.getReportRelationMap().get(reportForm.getId());
        if(CollectionUtils.isEmpty(reportRelationList)){
            return ;
        }
        // 获取对应的会计科目信息  筛选会计科目的Code
        List<String> accountList = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList());
        // 获取指定责任中心的收入数据
        Map<String, List<IncomeCollection>> respAccountIncomeMap = profitCalculationData.getRespIncomeGroup().get(responsibility.getResponsibilityCode());
        if(ObjectUtils.isEmpty(respAccountIncomeMap) || respAccountIncomeMap.isEmpty()){
            return ;
        }
        //获取指定会计科目的收入数据
        List<IncomeCollection> reportVOList=new ArrayList<>();
        accountList.forEach(accountCode -> {
            if(respAccountIncomeMap.containsKey(accountCode)){
                reportVOList.addAll(respAccountIncomeMap.get(accountCode));
            }
        });
        if(CollectionUtils.isEmpty(reportVOList)){
            return ;
        }
        BigDecimal totalAmount = reportVOList.stream()
                .map(IncomeCollection::getAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        costDepartmentProfitVO.setAmount(totalAmount);
    }

    /**
     *获取按成本会计科目计算的结果
     * @param profitCalculationData
     * @param responsibility
     * @param reportForm
     * @return
     */
    private void setCostAccountReportValue(CostDepartmentProfitVO costDepartmentProfitVO, ProfitCalculationDataVo profitCalculationData, Responsibility responsibility, ReportForm reportForm) {
        List<ReportRelation> reportRelationList = profitCalculationData.getReportRelationMap().get(reportForm.getId());
        if(CollectionUtils.isEmpty(reportRelationList)){
            return ;
        }
        // 获取对应的会计科目信息  筛选会计科目的Code
        List<String> accountList = reportRelationList.stream().map(ReportRelation::getRelationCode).collect(Collectors.toList());
        // 获取指定责任中心的分摊数据
        Map<String, List<AllocationQueryReportVO>> respAccountCostMap = profitCalculationData.getRespAccountCostGroup().get(responsibility.getResponsibilityCode());
        if(ObjectUtils.isEmpty(respAccountCostMap) || respAccountCostMap.isEmpty()){
            return ;
        }
        //获取指定会计科目的分摊数据
        List<AllocationQueryReportVO> reportVOList=new ArrayList<>();
        accountList.forEach(accountCode -> {
            if(respAccountCostMap.containsKey(accountCode)){
                reportVOList.addAll(respAccountCostMap.get(accountCode));
            }
        });
        if(CollectionUtils.isEmpty(reportVOList)){
            return ;
        }
        //获取指定成本类别(全部/直接/间接)的分摊数据
        List<AllocationQueryReportVO> collect = reportVOList.stream().filter(m -> NumberConstant.ZERO.equals(reportForm.getCostType()) || reportForm.getCostType().equals(m.getOriginType().intValue())).collect(Collectors.toList());
        if (CollUtil.isEmpty(reportVOList)) {
            return ;
        }
        List<CostDepartmentProfitAccount> costDepartmentProfitAccounts = calculateCostByTypeAndAccount(reportVOList);
        BigDecimal totalAmount = costDepartmentProfitAccounts.stream()
                .map(CostDepartmentProfitAccount::getAmount)
                .filter(Objects::nonNull)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        costDepartmentProfitVO.setAmount(totalAmount);
        costDepartmentProfitVO.setCostDepartmentProfitAccounts(costDepartmentProfitAccounts);
    }

    /**
     * 将分摊结果按会计科目类别+成本类别分组汇总
     * @param reportVOList
     * @return
     */
    public List<CostDepartmentProfitAccount> calculateCostByTypeAndAccount(List<AllocationQueryReportVO> reportVOList) {
        // 按costType+accountType分组计算各组的金额amount
        Map<String, BigDecimal> groupedAmounts = reportVOList.stream()
                .collect(Collectors.groupingBy(
                        vo -> vo.getCostType() + "_" + vo.getAccountType(),
                        Collectors.reducing(
                                BigDecimal.ZERO,
                                AllocationQueryReportVO::getAmount,
                                BigDecimal::add
                        )
                ));

        // 按组生成CostDepartmentProfitAccount对象
        return groupedAmounts.entrySet().stream()
                .map(entry -> {
                    String[] keys = entry.getKey().split("_", 2);
                    CostDepartmentProfitAccount account = new CostDepartmentProfitAccount();
                    account.setCostType(keys[0]);
                    account.setAccountType(keys[1]);
                    account.setAmount(entry.getValue());
                    return account;
                })
                .collect(Collectors.toList());
    }

    /**
     * 获取指定类型的报表配置
     * @param reportType
     * @return
     */
    public List<ReportForm> getReportForm(String reportType){
        List<ReportForm> reportFormList = reportFormService.list(new QueryWrapper<ReportForm>().lambda()
                .eq(ReportForm::getHospId,  UserContext.getHospId())
                .eq(ReportForm::getReportType, reportType));
        return reportFormList;
    }

    /**
     * 获取报表关系
     * @return
     */
    public List<ReportRelation> getReportRelation(){
        List<ReportRelation> list = reportRelationService.list(new QueryWrapper<ReportRelation>().lambda().eq(ReportRelation::getHospId, UserContext.getHospId()));
        return list;
    }

    /**
     * 获取指定报表对应的责任中心
     * @param reportType
     * @return
     */
    public List<Responsibility> getReportResponsibilityList(String reportType){
        DictDataVo dataVo = getDictDataVo(reportType);
        Long id = Long.valueOf(dataVo.getExpandOne());
        List<Responsibility> list = responsibilityService.list(new QueryWrapper<Responsibility>().lambda()
                .eq(Responsibility::getHospId, UserContext.getHospId())
                .eq(Responsibility::getIsGatherCenter, 2)
                .eq(Responsibility::getDeleteTime, 0)
                .eq(Responsibility::getShareId, id));
        return list;
    }


    /**
     * 获取分摊层级字典
     * @return
     */
    public List<CostShareLevel> getCostShareLevelList(){
        List<CostShareLevel> costShareLevelList =  costShareLevelService.list(new QueryWrapper<CostShareLevel>().lambda()
                .eq(CostShareLevel::getHospId, UserContext.getHospId()).orderByDesc(CostShareLevel::getLeverSort));
        return costShareLevelList;
    }

    /**
     * 获取归集后的收入数据
     * @param year
     * @param month
     * @return
     */
    public List<IncomeCollection> getIncomeCollectionList(Integer year, Integer month) {
        List<IncomeCollection> list = incomeCollectionService.list(new QueryWrapper<IncomeCollection>().lambda()
                .eq(IncomeCollection::getHospId, UserContext.getHospId())
                .eq(year > 0, IncomeCollection::getYear, year).eq(month > 0, IncomeCollection::getMonth, month));
        return list;
    }


    /**
     * 删除指定月份的科室损益数据
     * @param year
     * @param month
     * @param reportType
     */
    public void deleteDeptProfit(Integer year, Integer month,String reportType,Long hospId) {
        // 删除这个年月的数据
        this.remove(new QueryWrapper<CostDepartmentProfit>().lambda().eq(CostDepartmentProfit::getHospId, hospId)
                .eq(CostDepartmentProfit::getYear, year).eq(CostDepartmentProfit::getMonth, month).eq(CostDepartmentProfit::getShareType, Integer.valueOf(reportType)));
    }

}