package thyyxxk.webserver.service.medicalinsurance.costcontrol;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.constants.YbTjConstant;
import thyyxxk.webserver.constants.sidicts.TreatmentMethods;
import thyyxxk.webserver.dao.his.inpatient.casefrontsheet.CaseFrontSheetDao;
import thyyxxk.webserver.dao.his.medicalinsurance.costcontrol.YbCssTjDao;
import thyyxxk.webserver.entity.HeadInfo;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.casefrontsheet.DisefamilyGrade;
import thyyxxk.webserver.entity.casefrontsheet.OprnDisefamilyGrade;
import thyyxxk.webserver.entity.datamodify.ZyDetailCharge;
import thyyxxk.webserver.entity.medicalinsurance.inpatient.BatjBa4;
import thyyxxk.webserver.entity.medicalinsurance.inpatient.YbZyDisDiag;
import thyyxxk.webserver.entity.medicalinsurance.costcontrol.DeptChargeGroup;
import thyyxxk.webserver.entity.medicalinsurance.costcontrol.YbCssImp;
import thyyxxk.webserver.entity.medicalinsurance.costcontrol.YbCssSetlDeptInfo;
import thyyxxk.webserver.entity.medicalinsurance.costcontrol.YbCssSetlInfo;
import thyyxxk.webserver.entity.medicalinsurance.costcontrol.YbImpInfo;
import thyyxxk.webserver.entity.medicalinsurance.costcontrol.YbParamInfo;
import thyyxxk.webserver.entity.medicalinsurance.costcontrol.YbSetlInfo;
import thyyxxk.webserver.entity.medicalinsurance.costcontrol.YbkfShareDto;
import thyyxxk.webserver.utils.DecimalUtil;
import thyyxxk.webserver.utils.ExcelUtil;
import thyyxxk.webserver.utils.ListUtil;
import thyyxxk.webserver.utils.ResultVoUtil;
import thyyxxk.webserver.utils.StringUtil;
import thyyxxk.webserver.utils.YbReportUtil;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @ClassName YbCssTjService
 * @Description 长沙市医保数据统计
 * @Author hsh
 * @Date 2022/8/31 8:44
 **/
@Service
public class YbCssTjService {

    private final YbCssTjDao dao;

    private final CaseFrontSheetDao cfsDao;

    @Autowired
    public YbCssTjService(YbCssTjDao dao, CaseFrontSheetDao cfsDao) {
        this.dao = dao;
        this.cfsDao = cfsDao;
    }

    /**
     *@Author hsh
     *@Description // 长沙市医保数据导入查询
     *@Date 2022/8/31 11:28
     *@Param [dto]
     *@Return thyyxxk.webserver.entity.ResultVo<java.util.List<java.util.Map<java.lang.String,java.lang.Object>>>
     **/
    public ResultVo<List<Map<String, Object>>> selectCssYbJsTj(YbkfShareDto dto){
        String beginTime = dto.getStartTime();
        String endTime = dto.getEndTime();
        String deptId = dto.getDeptId();
        String insurName = dto.getInsurName();
        List<Map<String, Object>> result = dao.selectCssYbJsTj(beginTime, endTime, deptId, insurName);
        return ResultVoUtil.success(result);
    }

    /**
     * 长沙市医保数据-医生统计
     * @param dto
     * @return
     */
    public ResultVo<List<Map<String, Object>>> selectYsJsTj(YbkfShareDto dto){
        String beginTime = dto.getStartTime();
        String endTime = dto.getEndTime();
        String deptId = dto.getDeptId();
        String insurName = dto.getInsurName();
        List<Map<String, Object>> result = dao.selectYsJsTj(beginTime, endTime, deptId, insurName);
        return ResultVoUtil.success(result);
    }

    /**
     * 长沙市医保数据-医生统计
     * @param dto
     * @return
     */
    public ResultVo<Map<String, Object>> selectBrJsTj(YbkfShareDto dto){
        String beginTime = dto.getStartTime();
        String endTime = dto.getEndTime();
        String deptId = dto.getDeptId();
        String doctorId = dto.getDoctorId() == null ? "" : dto.getDoctorId();
        String insurName = dto.getInsurName();
        List<Map<String, Object>> result = dao.selectBrJsTj(beginTime, endTime, deptId, doctorId, insurName);
        Map<String, Object> m_total = dao.selectBrJsTjTotal(beginTime, endTime, deptId, doctorId, insurName);
        Map<String, Object> m = new HashMap<>();
        m.put("data", result);
        m.put("total", m_total);
        return ResultVoUtil.success(m);
    }

    /**
     *@Author hsh
     *@Description // 长沙市医保数据导入
     *@Date 2022/8/31 11:28
     *@Param [dto]
     *@Return void
     **/
    public ResultVo<String> ybCssImp(YbkfShareDto dto) {
        String insurName = dto.getInsurName();
        MultipartFile file = dto.getFile();
        String year = dto.getNf();
        try{
            List<YbCssImp> list = callYbImportData(insurName, file);
            System.out.println(list.size());
            if(list.size() > 0){

                // 更新历史数据
                dao.updateImportData(insurName, list);

                int count = 40;
                int batch = list.size() / count;
                if (list.size() % count != 0) {
                    batch = batch + 1;
                }

                //循环批量保存每组数据
                for (int i = 0; i < batch; i++) {
                    List<YbCssImp> subList;
                    if (i == batch - 1) {
                        subList = list.subList(count * i, list.size());
                    } else {
                        subList = list.subList(count * i, count * (i + 1));
                    }
                    // 入库
                    dao.batchInsertImportData(subList);
                }

                // 计算科室分摊
                // 获取当前年份的医保参数
                YbParamInfo paramInfo = dao.selectSetlYbParamInfo(insurName, year);
                if(paramInfo == null || paramInfo.getParamValue() == null){
                    return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
                }

                // 查询结算数据
                List<YbSetlInfo> setlList = dao.selectSetlInfo(list);
                count = 90;
                batch = setlList.size() / count;
                if (setlList.size() % count != 0) {
                    batch = batch + 1;
                }
                // 查询科室费用明细数据
                List<ZyDetailCharge> feeList = new ArrayList<>();
                for (int i = 0; i < batch; i++) {
                    List<YbSetlInfo> subList;
                    if (i == batch - 1) {
                        subList = setlList.subList(count * i, setlList.size());
                    } else {
                        subList = setlList.subList(count * i, count * (i + 1));
                    }
                    // 查询科室费用明细数据
                    feeList.addAll(dao.selectDeptShareFee(subList));
                }

                Map<String, List<ZyDetailCharge>> feeMap = feeList.stream().collect(Collectors.groupingBy(fee -> formatString(fee.getInpatientNo(), fee.getAdmissTimes(), fee.getLedgerSn())));

                // 生成长沙市医保结算表数据
                calCssSetlInfoData(paramInfo, list, setlList);

                //  生成长沙市医保科室差额表数据
                calCssDeptSetInfoData(paramInfo, list, setlList, feeMap);

            }
        }catch(Exception e){
            e.printStackTrace();
            return ResultVoUtil.fail(ExceptionEnum.NEED_PROOFREAD);
        }
        return ResultVoUtil.success("0");
    }

    /**
     *@Author hsh
     *@Description // 计算科室差额表
     *@Date 2022/9/7 17:28
     *@Param [paramInfo, list, setlList, feeMap]
     *@Return void
     **/
    private void calCssDeptSetInfoData(YbParamInfo paramInfo, List<YbCssImp> list, List<YbSetlInfo> setlList, Map<String, List<ZyDetailCharge>> feeMap) {
        List<YbCssSetlDeptInfo> setlDeptInfos = new ArrayList<>();
        for(YbCssImp imp : list){
            if("非正常数据".equals(imp.getDeclarationType())){
                continue;
            }

            // 获取医院his科室费用信息以及管床医生信息
            Optional<YbSetlInfo> first = setlList.stream().filter(setl -> Objects.equals(setl.getSetlId(),imp.getSetlId())).findFirst();
            if(first.isPresent()){
                String key = first.get().getPatNo() + "|" + first.get().getTimes() + "|" + first.get().getLedgerSn();
                List<ZyDetailCharge> feeList = feeMap.get(key);
                if(null != feeList && feeList.size() > 0){
                    Map<String, List<ZyDetailCharge>> fm = feeList.stream().collect(Collectors.groupingBy(ZyDetailCharge::getWardCode));
                    List<DeptChargeGroup> deptChargeList = callDeptChargeGroup(imp, fm);
                    if(deptChargeList.size() == 1){
                        setlDeptInfos.add(callOneYbCssSetlDeptInfo(paramInfo, imp, first.get(), deptChargeList.get(0)));
                    } else if(deptChargeList.size() > 1) {
                        setlDeptInfos.addAll(callElseYbCssSetlDeptInfo(paramInfo, imp, first.get(), deptChargeList));
                    }
                }
            }
        }

        if(setlDeptInfos.size() > 0){
            deleteAndInsertYbCssSetlDeptInfo(setlDeptInfos);
        }

    }

    // 更新医保结算科室差额数据
    private void deleteAndInsertYbCssSetlDeptInfo(List<YbCssSetlDeptInfo> setlDeptInfos) {
        dao.updateYbCssSetlDeptInfo(setlDeptInfos);

        int count = 40;
        int batch = setlDeptInfos.size() / count;
        if (setlDeptInfos.size() % count != 0) {
            batch = batch + 1;
        }

        //循环批量保存每组数据
        for (int i = 0; i < batch; i++) {
            List<YbCssSetlDeptInfo> subList;
            if (i == batch - 1) {
                subList = setlDeptInfos.subList(count * i, setlDeptInfos.size());
            } else {
                subList = setlDeptInfos.subList(count * i, count * (i + 1));
            }
            dao.insertYbCssSetlDeptInfo(subList);
        }
    }

    /**
     *@Author hsh
     *@Description // 有临床科室转科计算
     *@Date 2022/9/9 16:06
     *@Param [paramInfo, imp, ybSetlInfo, deptChargeList, ybDiaglist]
     *@Return java.util.List<thyyxxk.webserver.entity.ybkf.YbCssSetlDeptInfo>
     **/
    private List<YbCssSetlDeptInfo> callElseYbCssSetlDeptInfo(YbParamInfo paramInfo, YbCssImp imp, YbSetlInfo ybSetlInfo, List<DeptChargeGroup> deptChargeList) {
        List<YbCssSetlDeptInfo> list = new ArrayList<>();

        if("转科".equals(imp.getDeclarationType())){
            if(isZk(imp, ybSetlInfo, deptChargeList)){
                list.addAll(createZKSetlDeptInfo(paramInfo, imp, ybSetlInfo, deptChargeList));
            } else {
                list.addAll(createQtSetlDeptInfo(paramInfo, imp, ybSetlInfo, deptChargeList));
            }
        } else {
            list.addAll(createQtSetlDeptInfo(paramInfo, imp, ybSetlInfo, deptChargeList));
        }
        return list;
    }

    /**
     *@Author hsh
     *@Description // 计算转科的科室差额费用明细
     *@Date 2022/9/9 15:57
     *@Param [paramInfo, imp, ybSetlInfo, deptChargeList, ybDiaglist]
     *@Return java.util.List<thyyxxk.webserver.entity.ybkf.YbCssSetlDeptInfo>
     **/
    private List<YbCssSetlDeptInfo> createZKSetlDeptInfo(YbParamInfo paramInfo, YbCssImp imp, YbSetlInfo ybSetlInfo, List<DeptChargeGroup> deptChargeList) {
        List<YbCssSetlDeptInfo> list = new ArrayList<>();

        BigDecimal sumFundPay = BigDecimal.ZERO;

        for(int i = deptChargeList.size() - 1; i >= 0; i-- ){
            YbCssSetlDeptInfo deptInfo = new YbCssSetlDeptInfo();
            DeptChargeGroup ks = deptChargeList.get(i);
            // 第一个科室
            if(i == 0){
                deptInfo.setReimburseAmount(DecimalUtil.minus(imp.getReimburseAmount(), sumFundPay));
            } else {
                deptInfo.setReimburseAmount(DecimalUtil.multiply(imp.getReimburseAmount(), ks.getXs()));
                sumFundPay = DecimalUtil.add(deptInfo.getReimburseAmount(), sumFundPay);
            }
            deptInfo.setMedicalTotalFee(ks.getCharge());
            // 取计算好的分值
            deptInfo.setRealScore(ks.getScore());
            deptInfo.setSetlId(imp.getSetlId());
            deptInfo.setPatNo(imp.getPatNo());
            deptInfo.setTimes(ybSetlInfo.getTimes());
            deptInfo.setLedgerSn(ks.getLedgerSn());
            deptInfo.setMedinsType(imp.getMedinsType());
            deptInfo.setFlag("Y");
            deptInfo.setSettlTime(imp.getSettlTime());
            deptInfo.setCreateTime(new Date());

            // 计算预计支付和盈亏额
            BigDecimal ep = DecimalUtil.multiply(deptInfo.getRealScore(), new BigDecimal(paramInfo.getParamValue()));
            deptInfo.setEstimatedPayment(ep);
            deptInfo.setBal(DecimalUtil.minus(ep, deptInfo.getReimburseAmount()));

            // 科室以及医生信息
            deptInfo.setDeptId(ks.getDeptId());
            deptInfo.setDeptName(ks.getDeptName());
            deptInfo.setDoctorId(ks.getDoctorId());
            deptInfo.setDoctor(ks.getDoctor());
            if(ybSetlInfo.getDeptId().equals(ks.getDeptId())){
                deptInfo.setShortNo("1");
            } else {
                deptInfo.setShortNo("0");
            }
            list.add(deptInfo);
        }
        return list;
    }

    /**
     * 计算病种分值(改造caseFrontSheetMainService的方法：fetchSsfz)
     * @param code 医保诊断编码
     * @param bah 住院号
     * @param times 住院次数
     * @return 分值
     */
    private BigDecimal selectDiagScore(String code, String bah, Integer times) {
        DisefamilyGrade disefamilyGrade = cfsDao.selectDisefamilyGrade(code);
        if (null == disefamilyGrade) {
            return BigDecimal.ZERO;
        }
        boolean hasModified = cfsDao.selectModified(bah, times) > 0;
        List<String> surgeries = hasModified ? cfsDao.selectPatientSurgeryCodes(bah, times, "batj_ba4_modify")
                : cfsDao.selectPatientSurgeryCodes(bah, times, "batj_ba4");
        if (ListUtil.isBlank(surgeries)) {
            return BigDecimal.valueOf(disefamilyGrade.getNoneOprnGrade());
        }
        List<OprnDisefamilyGrade> oprnGrades = cfsDao.selectOperationDisefamilies(disefamilyGrade.getDisefamilyCode());
        int ssfz = 0;
        for (OprnDisefamilyGrade oprn : oprnGrades) {
            if (surgeries.contains(oprn.getOprnCode())) {
                if (oprn.getOprnGrade() > ssfz) {
                    ssfz = oprn.getOprnGrade();
                }
            }
        }
        if (ssfz != 0) {
            return BigDecimal.valueOf(ssfz);
        }
        return BigDecimal.valueOf(disefamilyGrade.getNoneOprnGrade());
    }

    /**
     *@Author hsh
     *@Description // 判断是否符合转科特征
     *@Date 2022/9/9 15:55
     *@Param [imp, ybSetlInfo, deptChargeList]
     *@Return boolean
     **/
    private boolean isZk(YbCssImp imp, YbSetlInfo ybSetlInfo, List<DeptChargeGroup> deptChargeList) {
        if(deptChargeList.size() != 2){
            return false;
        }

        List<YbZyDisDiag> zdList = dao.selectYbDiganInfo(ybSetlInfo.getPatNo(), ybSetlInfo.getTimes(), "zy_dis_diag_yb_modify");
        if(zdList.size() == 0){
            zdList = dao.selectYbDiganInfo(ybSetlInfo.getPatNo(), ybSetlInfo.getTimes(), "zy_dis_diag_yb");
        }

        Map<String, DeptChargeGroup> amp = new HashMap<>();
        for(DeptChargeGroup dept : deptChargeList){
            amp.put(dept.getDeptId(), dept);
        }

        BigDecimal lossScore = BigDecimal.ZERO;
        for (YbZyDisDiag item : zdList) {
            String deptCode = item.getDeptCode();
            if(1 == item.getDisDiagNo()){
                if(StringUtil.notBlank(deptCode)){
                    DeptChargeGroup dept = amp.get(deptCode);
                    if(dept == null){
                        return false;
                    }
                    BigDecimal fz = selectDiagScore(item.getDisDiag().trim(), ybSetlInfo.getPatNo(), ybSetlInfo.getTimes());
                    amp.get(deptCode).setScore(fz);
                    lossScore = DecimalUtil.minus(imp.getScore(), fz);
                } else {
                    return false;
                }
            } else {
                BigDecimal fz = selectDiagScore(item.getDisDiag().trim(), ybSetlInfo.getPatNo(), ybSetlInfo.getTimes());
                if(0d == DecimalUtil.minus(lossScore, fz).doubleValue()){
                    DeptChargeGroup dept = amp.get(deptCode);
                    if(dept == null){
                        return false;
                    } else {
                        amp.get(deptCode).setScore(fz);
                        return true;
                    }
                } else {
                    return false;
                }
            }
        }

        return false;
    }

    /**
     *@Author hsh
     *@Description // 计算普通临床科室转科治疗(按照科室费用分摊)的费用明细
     *@Date 2022/9/9 15:58
     *@Param [paramInfo, imp, ybSetlInfo, deptChargeList]
     *@Return java.util.List<thyyxxk.webserver.entity.ybkf.YbCssSetlDeptInfo>
     **/
    private List<YbCssSetlDeptInfo> createQtSetlDeptInfo(YbParamInfo paramInfo, YbCssImp imp, YbSetlInfo ybSetlInfo, List<DeptChargeGroup> deptChargeList) {
        List<YbCssSetlDeptInfo> list = new ArrayList<>();

        BigDecimal sumFundPay = BigDecimal.ZERO;
        BigDecimal sumScore = BigDecimal.ZERO;
        // 实际总分值
        BigDecimal realScore = DecimalUtil.minus(imp.getScore(), imp.getDeductScore() == null ? BigDecimal.ZERO : imp.getDeductScore());
        // 没有匹配到出院科室
        boolean notify_flag = true;

        for(int i = deptChargeList.size() - 1; i >= 0; i-- ){
            YbCssSetlDeptInfo deptInfo = new YbCssSetlDeptInfo();
            DeptChargeGroup ks = deptChargeList.get(i);
            // 第一个科室
            if(i == 0){
                deptInfo.setReimburseAmount(DecimalUtil.minus(imp.getReimburseAmount(), sumFundPay));
                deptInfo.setRealScore(DecimalUtil.minus(realScore, sumScore));
            } else {
                deptInfo.setReimburseAmount(DecimalUtil.multiply(imp.getReimburseAmount(), ks.getXs()));
                sumFundPay = DecimalUtil.add(deptInfo.getReimburseAmount(), sumFundPay);
                deptInfo.setRealScore(DecimalUtil.multiply(realScore, ks.getXs()));
                sumScore = DecimalUtil.add(deptInfo.getRealScore(), sumScore);
            }
            deptInfo.setMedicalTotalFee(ks.getCharge());
            deptInfo.setSetlId(imp.getSetlId());
            deptInfo.setPatNo(imp.getPatNo());
            deptInfo.setTimes(ybSetlInfo.getTimes());
            deptInfo.setLedgerSn(ks.getLedgerSn());
            deptInfo.setMedinsType(imp.getMedinsType());
            deptInfo.setFlag("Y");
            deptInfo.setCreateTime(new Date());
            deptInfo.setSettlTime(imp.getSettlTime());
            // 计算预计支付和盈亏额
            if("单列".equals(imp.getDeclarationType())){
                deptInfo.setBal(BigDecimal.ZERO);
                deptInfo.setEstimatedPayment(deptInfo.getReimburseAmount());
            } else {
                BigDecimal ep = DecimalUtil.multiply(deptInfo.getRealScore(), new BigDecimal(paramInfo.getParamValue()));
                deptInfo.setEstimatedPayment(ep);
                deptInfo.setBal(DecimalUtil.minus(ep, deptInfo.getReimburseAmount()));
            }

            // 科室以及医生信息
            deptInfo.setDeptId(ks.getDeptId());
            deptInfo.setDeptName(ks.getDeptName());
            deptInfo.setDoctorId(ks.getDoctorId());
            deptInfo.setDoctor(ks.getDoctor());

            if(ybSetlInfo.getDeptId().equals(ks.getDeptId())){
                deptInfo.setShortNo("1");
                notify_flag = false;
            } else {
                deptInfo.setShortNo("0");
            }
            list.add(deptInfo);
        }

        // 科室不匹配
        if(notify_flag){
            // 取科室费用最多的科室为算人数科室
            // 重症医学科不能作为算人数科室, 顺延至下一个科室
            list.sort(Comparator.comparing(YbCssSetlDeptInfo::getMedicalTotalFee).reversed());

            if(YbTjConstant.ICU_DEPT.equals(list.get(0).getDeptId())){
                list.get(1).setShortNo("1");
            } else {
                list.get(0).setShortNo("1");
            }

        }

        return list;
    }

    /**
     *@Author hsh
     *@Description // 没有临床科室转科计算
     *@Date 2022/9/8 14:26
     *@Param [paramInfo, imp, ybSetlInfo, deptChargeGroup]
     *@Return thyyxxk.webserver.entity.ybkf.YbCssSetlDeptInfo
     **/
    private YbCssSetlDeptInfo callOneYbCssSetlDeptInfo(YbParamInfo paramInfo, YbCssImp imp, YbSetlInfo ybSetlInfo, DeptChargeGroup deptChargeGroup) {
        YbCssSetlDeptInfo setlDeptInfo = new YbCssSetlDeptInfo();

        setlDeptInfo.setSetlId(imp.getSetlId());
        setlDeptInfo.setPatNo(imp.getPatNo());
        setlDeptInfo.setMedinsType(imp.getMedinsType());
        setlDeptInfo.setSettlTime(imp.getSettlTime());
        setlDeptInfo.setLedgerSn(deptChargeGroup.getLedgerSn());

        // 补充医院his管床科室以及医生信息
        if(ybSetlInfo != null){
            if(null != ybSetlInfo.getDeptId() && ybSetlInfo.getDeptId().equals(deptChargeGroup.getDeptId())){
                setlDeptInfo.setDeptId(ybSetlInfo.getDeptId());
                setlDeptInfo.setDeptName(ybSetlInfo.getDeptName());
            } else {
                setlDeptInfo.setDeptId(deptChargeGroup.getDeptId());
                setlDeptInfo.setDeptName(deptChargeGroup.getDeptName());
            }
            if(null != ybSetlInfo.getDoctorId() && ybSetlInfo.getDoctorId().equals(deptChargeGroup.getDoctorId())){
                setlDeptInfo.setDoctorId(ybSetlInfo.getDoctorId());
                setlDeptInfo.setDoctor(ybSetlInfo.getDoctor());
            } else {
                setlDeptInfo.setDoctorId(deptChargeGroup.getDoctorId());
                setlDeptInfo.setDoctor(deptChargeGroup.getDoctor());
            }
            setlDeptInfo.setTimes(ybSetlInfo.getTimes());
        }
        setlDeptInfo.setMedicalTotalFee(imp.getMedicalTotalFee());
        setlDeptInfo.setReimburseAmount(imp.getReimburseAmount());

        // 常量设置
        setlDeptInfo.setCreateTime(new Date());
        setlDeptInfo.setShortNo("1");
        setlDeptInfo.setFlag("Y");
        setlDeptInfo.setRealScore(DecimalUtil.minus(imp.getScore(), imp.getDeductScore() == null ? BigDecimal.ZERO : imp.getDeductScore()));

        // 计算预计支付以及盈亏额
        if("单列".equals(imp.getDeclarationType())){
            setlDeptInfo.setBal(BigDecimal.ZERO);
            setlDeptInfo.setEstimatedPayment(setlDeptInfo.getReimburseAmount());
        } else {
            BigDecimal ep = DecimalUtil.multiply(setlDeptInfo.getRealScore(), new BigDecimal(paramInfo.getParamValue()));
            setlDeptInfo.setEstimatedPayment(ep);
            setlDeptInfo.setBal(DecimalUtil.minus(ep, setlDeptInfo.getReimburseAmount()));
        }
        return setlDeptInfo;
    }

    private List<DeptChargeGroup> callDeptChargeGroup(YbCssImp imp, Map<String, List<ZyDetailCharge>> fm) {
        List<DeptChargeGroup> chargeList = new ArrayList<>();
        for(Map.Entry<String, List<ZyDetailCharge>> entry : fm.entrySet()){
            DeptChargeGroup deptChargeGroup = new DeptChargeGroup();
            String key = entry.getKey();
            BigDecimal fee = BigDecimal.ZERO;
            List<ZyDetailCharge> list = entry.getValue();
            String doctorId = "";
            String doctor = "";
            for(ZyDetailCharge charge : list){
                fee = DecimalUtil.add(fee, charge.getChargeFee());
                if(StringUtil.notBlank(charge.getReferPhysician())){
                    doctorId = charge.getReferPhysician();
                }
                // sql查询借助这个字段存医生名字
                if(StringUtil.notBlank(charge.getConsultPhysician())){
                    doctor = charge.getConsultPhysician();
                }
            }
            deptChargeGroup.setDeptId(key);
            // sql查询借助这个字段存科室名称
            deptChargeGroup.setDeptName(list.get(0).getExecUnitName());
            deptChargeGroup.setCharge(fee);
            deptChargeGroup.setDoctorId(doctorId);
            deptChargeGroup.setDoctor(doctor);
            deptChargeGroup.setLedgerSn(list.get(0).getLedgerSn());
            chargeList.add(deptChargeGroup);

            // 计算各个科室的占比系数
            if(chargeList.size() == 1){
                chargeList.get(0).setXs(BigDecimal.ONE);
            } else {
                BigDecimal sumXs = null;
                for(int i = chargeList.size() - 1; i >= 0; i-- ){
                    DeptChargeGroup dept =  chargeList.get(i);
                    if(i == 0){
                        dept.setXs(DecimalUtil.minus(BigDecimal.ONE, sumXs));
                    } else {
                        dept.setXs(DecimalUtil.divide(dept.getCharge(), imp.getMedicalTotalFee(), YbReportUtil.getYxws(dept.getCharge())));
                        sumXs = DecimalUtil.add(dept.getXs(), sumXs);
                    }
                }
            }
        }

        return chargeList;
    }

    /**
     *@Author hsh
     *@Description // 计算市医保结算表
     *@Date 2022/9/7 8:59
     *@Param [paramInfo, list, setlList, feeMap]
     *@Return void
     **/
    private void calCssSetlInfoData(YbParamInfo paramInfo, List<YbCssImp> list, List<YbSetlInfo> setlList) {
        List<YbCssSetlInfo> cssSetlInfoList = new ArrayList<>();
        // 计算市医保结算表
        for(YbCssImp imp : list){
            YbCssSetlInfo info = new YbCssSetlInfo();
            if("非正常数据".equals(imp.getDeclarationType())){
                continue;
            }

            info.setSetlId(imp.getSetlId());
            info.setPatNo(imp.getPatNo());
            info.setMedinsType(imp.getMedinsType());
            info.setPsnName(imp.getPsnName());

            // 补充医院his管床科室以及医生信息, *****账页号*****
            Optional<YbSetlInfo> first = setlList.stream().filter(setl -> Objects.equals(setl.getSetlId(),imp.getSetlId())).findFirst();
            if(first.isPresent()){
                info.setDeptId(first.get().getDeptId());
                info.setDeptName(first.get().getDeptName());
                info.setDoctorId(first.get().getDoctorId());
                info.setDoctor(first.get().getDoctor());
                info.setTimes(first.get().getTimes());
                // *****账页号***** 相当于我们之前的断账次数
                info.setLedgerSn(first.get().getLedgerSn());
                // 正常
                info.setFlag("0");
            } else {
                // 没有院内对应的管床科室和医生
                info.setFlag("9");
            }
            info.setIdCard(imp.getIdCard());
            info.setIllCode(imp.getIllCode());
            info.setIllName(imp.getIllName());
            info.setMainDiagnCode(imp.getMainDiagnCode());
            info.setMainDiagnName(imp.getMainDiagnName());
            info.setMainOperateCode(imp.getMainOperateCode());
            info.setMainOperateName(imp.getMainOperateName());
            info.setIndays(imp.getIndays());
            info.setMedicalTotalFee(imp.getMedicalTotalFee());
            info.setReimburseAmount(imp.getReimburseAmount());
            info.setTreatment(imp.getTreatment());
            info.setDeclarationType(imp.getDeclarationType());
            info.setScore(imp.getScore());
            info.setDeductScore(imp.getDeductScore());
            info.setAdmissionTime(imp.getAdmissionTime());
            info.setDischargeTime(imp.getDischargeTime());
            info.setSettlTime(imp.getSettlTime());

            // 常量设置
            info.setCreateTime(new Date());
            info.setRealScore(DecimalUtil.minus(info.getScore(), info.getDeductScore() == null ? BigDecimal.ZERO : info.getDeductScore()));

            // 计算预计支付以及盈亏额
            if("单列".equals(info.getDeclarationType())){
                info.setBal(BigDecimal.ZERO);
                info.setEstimatedPayment(info.getReimburseAmount());
            } else {
                BigDecimal ep = DecimalUtil.multiply(info.getRealScore(), new BigDecimal(paramInfo.getParamValue()));
                info.setEstimatedPayment(ep);
                info.setBal(DecimalUtil.minus(ep, info.getReimburseAmount()));
            }

            cssSetlInfoList.add(info);
        }

        deleteAndInsertYbCssSetlInfo(cssSetlInfoList);
    }

    // 更新市医保结算表数据
    private void deleteAndInsertYbCssSetlInfo(List<YbCssSetlInfo> cssSetlInfoList) {
        if(cssSetlInfoList.size() > 0){
            dao.updateYbCssSetlInfoData(cssSetlInfoList);

            int count = 40;
            int batch = cssSetlInfoList.size() / count;
            if (cssSetlInfoList.size() % count != 0) {
                batch = batch + 1;
            }

            //循环批量保存每组数据
            for (int i = 0; i < batch; i++) {
                List<YbCssSetlInfo> subList;
                if (i == batch - 1) {
                    subList = cssSetlInfoList.subList(count * i, cssSetlInfoList.size());
                } else {
                    subList = cssSetlInfoList.subList(count * i, count * (i + 1));
                }
                dao.insertYbCssSetlInfoData(subList);
            }

        }
    }

    /**
     *@Author hsh
     *@Description // 解析导入excel医保数据
     *@Date 2022/9/7 8:58
     *@Param [insurName, file]
     *@Return java.util.List<thyyxxk.webserver.entity.ybkf.YbCssImp>
     **/
    private List<YbCssImp> callYbImportData(String insurName, MultipartFile file) throws IOException {
        List<YbImpInfo> xhs = dao.getImpXh(insurName);
        int xm = 0,sfzh=1,bzbm=2,bzmc=3,zyzdbm=4,zyzdmc=5,zyssbm=6,zyssmc=7,zyts=8,ylzfy=9,bxje=10,zlfs=11,sblx=12,fz=13,kfz=14,kfbz=15,ks=16,ys=17,rysj=18,cysj=19,jssj=20,zyh=22,jslsh = 23;
        for(YbImpInfo impInfo : xhs){
            // 姓名
            if("xm".equals(impInfo.getImpCode())){
                xm = impInfo.getImpXh();
            }
            // 身份证号
            if("sfzh".equals(impInfo.getImpCode())){
                sfzh = impInfo.getImpXh();
            }
            // 病种编码
            if("bzbm".equals(impInfo.getImpCode())){
                bzbm = impInfo.getImpXh();
            }
            // 病种名称
            if("bzmc".equals(impInfo.getImpCode())){
                bzmc = impInfo.getImpXh();
            }
            // 主要诊断编码
            if("zyzdbm".equals(impInfo.getImpCode())){
                zyzdbm = impInfo.getImpXh();
            }
            // 主要诊断名称
            if("zyzdmc".equals(impInfo.getImpCode())){
                zyzdmc = impInfo.getImpXh();
            }
            // 主要手术操作编码
            if("zyssbm".equals(impInfo.getImpCode())){
                zyssbm = impInfo.getImpXh();
            }
            // 主要手术操作名称
            if("zyssmc".equals(impInfo.getImpCode())){
                zyssmc = impInfo.getImpXh();
            }
            // 住院天数
            if("zyts".equals(impInfo.getImpCode())){
                zyts = impInfo.getImpXh();
            }
            // 医疗费用总额(元)
            if("ylzfy".equals(impInfo.getImpCode())){
                ylzfy = impInfo.getImpXh();
            }
            // 报销金额(元)
            if("bxje".equals(impInfo.getImpCode())){
                bxje = impInfo.getImpXh();
            }
            // 治疗方式
            if("zlfs".equals(impInfo.getImpCode())){
                zlfs = impInfo.getImpXh();
            }
            // 申报类型
            if("sblx".equals(impInfo.getImpCode())){
                sblx = impInfo.getImpXh();
            }
            // 分值
            if("fz".equals(impInfo.getImpCode())){
                fz = impInfo.getImpXh();
            }
            // 扣分值
            if("kfz".equals(impInfo.getImpCode())){
                kfz = impInfo.getImpXh();
            }
            // 扣分备注
            if("kfbz".equals(impInfo.getImpCode())){
                kfbz = impInfo.getImpXh();
            }
            // 扣分值
            if("kfz".equals(impInfo.getImpCode())){
                kfz = impInfo.getImpXh();
            }
            // 扣分备注
            if("kfbz".equals(impInfo.getImpCode())){
                kfbz = impInfo.getImpXh();
            }
            // 科室
            if("ks".equals(impInfo.getImpCode())){
                ks = impInfo.getImpXh();
            }
            // 医生
            if("ys".equals(impInfo.getImpCode())){
                ys = impInfo.getImpXh();
            }
            // 入院时间
            if("rysj".equals(impInfo.getImpCode())){
                rysj = impInfo.getImpXh();
            }
            // 出院时间
            if("cysj".equals(impInfo.getImpCode())){
                cysj = impInfo.getImpXh();
            }
            // 结算时间
            if("jssj".equals(impInfo.getImpCode())){
                jssj = impInfo.getImpXh();
            }
            // 医院住院号
            if("zyh".equals(impInfo.getImpCode())){
                zyh = impInfo.getImpXh();
            }
            // 结算流水号
            if("jslsh".equals(impInfo.getImpCode())){
                jslsh = impInfo.getImpXh();
            }
        }

        InputStream is = null;
        Workbook workbook;
        // 导入数据接收list
        List<YbCssImp> impList = new ArrayList<>();
        StringBuilder str = new StringBuilder();

        try {
            is = file.getInputStream();
            workbook = WorkbookFactory.create(is);
            // 获取第一个活页数据
            Sheet sheet = workbook.getSheetAt(0);
            // 第几行开始解析
            int rowStart = 2;
            for (int i = rowStart; i <= sheet.getLastRowNum(); i++) {
                Row row = sheet.getRow(i);
                if(null == row.getCell(0) || StringUtil.isBlank(row.getCell(0).getStringCellValue())){
                    continue;
                }
                // 获取行所有单元格数据
                int colNum = row.getPhysicalNumberOfCells();
                int j = 0;
                while(j < colNum){
                    str.append(getCellStringVal(row.getCell(j)).trim()).append("_");
                    j ++;
                }
                YbCssImp imp = new YbCssImp();
                String[] stirs = str.toString().split("_");
                imp.setPsnName(stirs[xm]);
                imp.setIdCard(stirs[sfzh]);
                imp.setIllCode(stirs[bzbm]);
                imp.setIllName(stirs[bzmc]);
                imp.setMainDiagnCode(stirs[zyzdbm]);
                imp.setMainDiagnName(stirs[zyzdmc]);
                imp.setMainOperateCode(stirs[zyssbm]);
                imp.setMainOperateName(stirs[zyssmc]);
                if(StringUtil.notBlank(stirs[zyts])){
                    imp.setIndays(Integer.valueOf(stirs[zyts]));
                }
                if(StringUtil.notBlank(stirs[ylzfy])){
                    imp.setMedicalTotalFee(new BigDecimal(stirs[ylzfy]));
                }
                if(StringUtil.notBlank(stirs[bxje])){
                    imp.setReimburseAmount(new BigDecimal(stirs[bxje]));
                }
                imp.setTreatment(stirs[zlfs]);
                imp.setDeclarationType(stirs[sblx]);
                if(StringUtil.notBlank(stirs[fz])){
                    imp.setScore(new BigDecimal(stirs[fz]));
                }
                if(StringUtil.notBlank(stirs[kfz])){
                    imp.setDeductScore(new BigDecimal(stirs[kfz]));
                }
                imp.setDeductScoreRemark(stirs[kfbz]);
                imp.setYbDeptCode(stirs[ks]);
                imp.setDoctor(stirs[ys]);
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                if(StringUtil.notBlank(stirs[rysj])){
                    Date sj = sdf.parse(stirs[rysj]);
                    imp.setAdmissionTime(sj);
                }
                if(StringUtil.notBlank(stirs[cysj])){
                    Date sj = sdf.parse(stirs[cysj]);
                    imp.setDischargeTime(sj);
                }
                if(StringUtil.notBlank(stirs[jssj])){
                    Date sj = sdf.parse(stirs[jssj]);
                    imp.setSettlTime(sj);
                }
                imp.setPatNo(stirs[zyh]);
                imp.setSetlId(stirs[jslsh]);

                // 常量
                imp.setMedinsType(insurName);
                imp.setImpTime(new Date());
                // 导入数据有效
                if("非正常数据".equals(imp.getDeclarationType())){
                    imp.setFlag("2");
                } else {
                    imp.setFlag("0");
                }
                imp.setHospitalNo("H32132200561");
                imp.setHospitalName("湖南泰和医院管理有限公司");
                impList.add(imp);
                str = new StringBuilder();
            }
            workbook.close();
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(is != null){
                is.close();
            }
        }

        return impList;
    }

    /**
     *@Author hsh
     *@Description // 解析excel的单元格数据类型
     *@Date 2022/9/2 16:40
     *@Param [cell]
     *@Return java.lang.String
     **/
    private String getCellStringVal(Cell cell) {
        String cellType = cell.getCellType().name();
        switch (cellType) {
            case "NUMERIC":
                short format = cell.getCellStyle().getDataFormat();
                if (DateUtil.isCellDateFormatted(cell)) {
                    SimpleDateFormat sdf;
                    if (format == 20 || format == 32) {
                        sdf = new SimpleDateFormat("HH:mm");
                    } else if (format == 14 || format == 31 || format == 57 || format == 58) {
                        // 处理自定义日期格式：m月d日(通过判断单元格的格式id解决，id的值是58)
                        sdf = new SimpleDateFormat("yyyy-MM-dd");
                        double value = cell.getNumericCellValue();
                        Date date = DateUtil.getJavaDate(value);
                        return sdf.format(date);
                    } else {
                        // 日期
                        sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    }
                    return sdf.format(cell.getDateCellValue());
                }  else {
                    BigDecimal bd = BigDecimal.valueOf(cell.getNumericCellValue());
                    // 数值 用BigDecimal包装再获取plainString，可以防止获取到科学计数值
                    return bd.toPlainString();
                }
            case "STRING":
                return cell.getRichStringCellValue().getString();
            case "BOOLEAN":
                return String.valueOf(cell.getBooleanCellValue());
            case "FORMULA":
                return cell.getCellFormula();
            case "ERROR":
                return String.valueOf(cell.getErrorCellValue());
            default:
                return "";
        }
    }

    private String formatString(Object... paras) {
        return MessageFormat.format("{0}|{1}|{2}", paras);
    }

    /**
     * 导出科室数据
     * @param response
     * @param dto
     * @return
     */
    public void exportKsYbSetlExcel(HttpServletResponse response, YbkfShareDto dto){
        String beginTime = dto.getStartTime();
        String endTime = dto.getEndTime();
        String deptId = dto.getDeptId();
        String insurName = dto.getInsurName();
        ResultVo<List<Map<String, Object>>> rs =  selectCssYbJsTj(dto);
        List<Map<String, Object>> list = rs.getData();

        if(null == list){
            return;
        }

        // 查询合计
        Map<String, Object> m_total = dao.selectCssYbJsTjTotal(beginTime, endTime, deptId, insurName);
        list.add(m_total);

        // 导出标题
        String exportName = "市医保结算统计(科室)";

        // 组装表头
        List<HeadInfo> headInfoList = calYbSetlHeadList("ks");

        // 导出
        ExcelUtil.exportExcelReport(response, list, headInfoList, exportName);
    }

    /**
     * 导出医生数据
     * @param response
     * @param dto
     * @return
     */
    public void exportYsYbSetlExcel(HttpServletResponse response, YbkfShareDto dto){
        String beginTime = dto.getStartTime();
        String endTime = dto.getEndTime();
        String deptId = dto.getDeptId();
        String insurName = dto.getInsurName();
        ResultVo<List<Map<String, Object>>> rs =  selectYsJsTj(dto);
        List<Map<String, Object>> list = rs.getData();

        if(null == list){
            return;
        }

        // 查询合计
        Map<String, Object> m_total = dao.selectYsJsTjTotal(beginTime, endTime, deptId, insurName);
        list.add(m_total);

        // 导出标题
        String exportName = "市医保结算统计(医生)";

        // 组装表头
        List<HeadInfo> headInfoList = calYbSetlHeadList("ys");

        // 导出
        ExcelUtil.exportExcelReport(response, list, headInfoList, exportName);
    }

    /**
     * 导出病人数据
     * @param response
     * @param dto
     * @return
     */
    public void exportBrYbSetlExcel(HttpServletResponse response, YbkfShareDto dto){
        ResultVo<Map<String, Object>> rs =  selectBrJsTj(dto);
        Map<String, Object> mapData = rs.getData();

        if(null == mapData){
            return;
        }

        List<Map<String, Object>> list = (List<Map<String, Object>>) mapData.get("data");
        // 主要诊断和主要手术需要重新组合一下编码和名称
        for(Map<String, Object> map : list){
            String zdmc = String.valueOf(map.get("zdmc"));
            String zdbm = String.valueOf(map.get("zdbm"));
            String ssmc = String.valueOf(map.get("ssmc"));
            String ssbm = String.valueOf(map.get("ssbm"));
            zdmc = zdmc + "(" + zdbm + ")";
            if(StringUtil.notBlank(ssbm)){
                ssmc = ssmc + "(" + ssbm + ")";
            }
            map.put("zdmc", zdmc);
            map.put("ssmc", ssmc);
        }

        // 查询合计
        Map<String, Object> m_total = (Map<String, Object>) mapData.get("total");
        list.add(m_total);

        // 导出标题
        String exportName = "市医保结算统计(病人)";

        // 组装表头
        List<HeadInfo> headInfoList = calYbSetlHeadList("br");

        // 导出
        ExcelUtil.exportExcelReport(response, list, headInfoList, exportName);
    }

    /**
     * 医保数据导出表头组装
     * @param type ks: 科室， ys： 医生， br： 病人
     * @return
     */
    private List<HeadInfo> calYbSetlHeadList(String type) {
        List<HeadInfo> headList = new ArrayList<>();

        if("br".equals(type)){
            HeadInfo headInfo = new HeadInfo();
            headInfo.setDisplay("科室");
            headInfo.setName("deptName");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("医生");
            headInfo.setName("doctor");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("住院号");
            headInfo.setName("zyh");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("姓名");
            headInfo.setName("xm");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("险种");
            headInfo.setName("yblx");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("总费用");
            headInfo.setName("zfy");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("预计支付");
            headInfo.setName("yjzf");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("统筹支付");
            headInfo.setName("tczf");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("盈亏额");
            headInfo.setName("bal");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("报销比例(%)");
            headInfo.setName("bxbl");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("总分值");
            headInfo.setName("zfz");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("治疗方式");
            headInfo.setName("zlfs");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("申报类型");
            headInfo.setName("sblx");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("主要诊断");
            headInfo.setName("zdmc");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("主要手术");
            headInfo.setName("ssmc");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("结算时间");
            headInfo.setName("jssj");
            headList.add(headInfo);
        } else {
            HeadInfo headInfo = new HeadInfo();
            headInfo.setDisplay("科室");
            headInfo.setName("deptName");
            headList.add(headInfo);

            if("ys".equals(type)){
                headInfo = new HeadInfo();
                headInfo.setDisplay("医生");
                headInfo.setName("doctor");
                headList.add(headInfo);
            }

            headInfo = new HeadInfo();
            headInfo.setDisplay("总费用");
            headInfo.setName("zfy");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("预计支付");
            headInfo.setName("yjzf");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("统筹支付");
            headInfo.setName("tczf");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("盈亏额");
            headInfo.setName("bal");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("报销比例(%)");
            headInfo.setName("bxbl");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("总人数");
            headInfo.setName("zrs");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("总分值");
            headInfo.setName("zfz");
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("有对照");
            headInfo.setName("ydz");

            List<HeadInfo> headInfoList = new ArrayList<>();
            HeadInfo headInfo1 = new HeadInfo();
            headInfo1.setDisplay("人数");
            headInfo1.setName("ydzrs");
            headInfoList.add(headInfo1);

            headInfo1 = new HeadInfo();
            headInfo1.setDisplay("盈亏额");
            headInfo1.setName("ydzbal");
            headInfoList.add(headInfo1);

            headInfo.setColumns(headInfoList);
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("无对照");
            headInfo.setName("wdz");

            headInfoList = new ArrayList<>();
            headInfo1 = new HeadInfo();
            headInfo1.setDisplay("人数");
            headInfo1.setName("wdzrs");
            headInfoList.add(headInfo1);

            headInfo1 = new HeadInfo();
            headInfo1.setDisplay("盈亏额");
            headInfo1.setName("wdzbal");
            headInfoList.add(headInfo1);

            headInfo.setColumns(headInfoList);
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("难度系数");
            headInfo.setName("ndxs");

            headInfoList = new ArrayList<>();
            headInfo1 = new HeadInfo();
            headInfo1.setDisplay("人数");
            headInfo1.setName("ndxsrs");
            headInfoList.add(headInfo1);

            headInfo1 = new HeadInfo();
            headInfo1.setDisplay("盈亏额");
            headInfo1.setName("ndxsbal");
            headInfoList.add(headInfo1);

            headInfo.setColumns(headInfoList);
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("治疗未完成");
            headInfo.setName("wwc");

            headInfoList = new ArrayList<>();
            headInfo1 = new HeadInfo();
            headInfo1.setDisplay("人数");
            headInfo1.setName("wwcrs");
            headInfoList.add(headInfo1);

            headInfo1 = new HeadInfo();
            headInfo1.setDisplay("盈亏额");
            headInfo1.setName("wwcbal");
            headInfoList.add(headInfo1);

            headInfo.setColumns(headInfoList);
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("转科");
            headInfo.setName("zk");

            headInfoList = new ArrayList<>();
            headInfo1 = new HeadInfo();
            headInfo1.setDisplay("人数");
            headInfo1.setName("zkrs");
            headInfoList.add(headInfo1);

            headInfo1 = new HeadInfo();
            headInfo1.setDisplay("盈亏额");
            headInfo1.setName("zkbal");
            headInfoList.add(headInfo1);

            headInfo.setColumns(headInfoList);
            headList.add(headInfo);

            headInfo = new HeadInfo();
            headInfo.setDisplay("单列");
            headInfo.setName("dlrs");
            headList.add(headInfo);

        }

        return headList;
    }

    /**
     * @description: 长沙市医保出院测算查询
     * @author: hsh
     * @date: 2022/9/22 17:13
     * @param: [dto]
     * @return: ResultVo<List<Map<String,Object>>>
     **/
    public ResultVo<Map<String, Object>> selectCssYbCsTj(YbkfShareDto dto){
        String beginTime = dto.getStartTime();
        String endTime = dto.getEndTime();
        String dept = dto.getDept();
        String insurName = dto.getInsurName();
        String zyh = dto.getZyh();
        List<Map<String, Object>> result = dao.selectCssYbCsTj(beginTime, endTime, dept, insurName, zyh);

        // 获取当年长沙市分值测算标准(setl_cc: 决算; test_cc: 测算)
        String year = endTime.substring(0,4);
        List<YbParamInfo> testParams = dao.selectYbParamInfoByYear(year, "test_cc");
        List<YbParamInfo> setlParams = dao.selectYbParamInfoByYear(year, "setl_cc");

        // 补充主诊断、主手术、分值、预计支付，计算预计的盈亏额
        for(Map<String, Object> map : result){
            AddDaginAndBal(testParams, setlParams, map);
        }
        // 计算合计
        Map<String, Object> hjMap = new HashMap<>();
        String zfy = "0";
        String yjzf = "0";
        String tczf = "0";
        String bal = "0";
        String score = "0";
        String bxbl = "0";
        for(Map<String, Object> map : result){
            zfy = DecimalUtil.add(zfy, String.valueOf(map.get("zfy")));
            yjzf = DecimalUtil.add(yjzf, String.valueOf(map.get("yjzf")));
            tczf = DecimalUtil.add(tczf, String.valueOf(map.get("tczf")));
            bal = DecimalUtil.add(bal, String.valueOf(map.get("bal")));
            score = DecimalUtil.add(score, String.valueOf(map.get("score")));
            bxbl = String.valueOf(DecimalUtil.multiply(new BigDecimal(DecimalUtil.divide(tczf, zfy, 4)), new BigDecimal("100")));
        }
        hjMap.put("zfy", zfy);
        hjMap.put("yjzf", yjzf);
        hjMap.put("tczf", tczf);
        hjMap.put("bal", bal);
        hjMap.put("score", score);
        hjMap.put("bxbl", bxbl);
        hjMap.put("data", result);
        return ResultVoUtil.success(hjMap);
    }

    /**
     * @description: 补充主诊断、主手术、分值、预计支付，计算预计的盈亏额
     * @author: hsh
     * @date: 2022/9/26 15:44
     * @param: [paramInfoList, map]
     * @return: void
     **/
    private void AddDaginAndBal(List<YbParamInfo> testParams, List<YbParamInfo> setlParams, Map<String, Object> map) {
        // 获取标准分值
        String medinsType = String.valueOf(map.get("yblx"));
        if(StringUtil.isBlank(medinsType)){
            return;
        }
        BigDecimal csbz = BigDecimal.ONE;
        for(YbParamInfo param : testParams){
            if(medinsType.equals(param.getMedinsType())){
                csbz = new BigDecimal(param.getParamValue());
                break;
            }
        }
        BigDecimal jsbz = BigDecimal.ONE;
        for(YbParamInfo param : setlParams){
            if(medinsType.equals(param.getMedinsType())){
                jsbz = new BigDecimal(param.getParamValue());
                break;
            }
        }

        // 治疗方式与申报类型
        String zlfs = map.get("zlfs") + "";
        map.put("zlfs", TreatmentMethods.get(zlfs).getName());

        String zyh = map.get("zyh") + "";
        Integer times = Integer.parseInt(map.get("zycs") + "");

        List<YbZyDisDiag> zdList = dao.selectYbDiganInfo(zyh, times, "zy_dis_diag_yb_modify");
        if(zdList.size() == 0){
            zdList = dao.selectYbDiganInfo(zyh, times, "zy_dis_diag_yb");
        }

        List<BatjBa4> ba4List = dao.selectYbOprtInfo(zyh, times, "batj_ba4_modify");
        if(ba4List.size() == 0){
            ba4List = dao.selectYbOprtInfo(zyh, times, "batj_ba4");
        }

        BigDecimal tczf = new BigDecimal(map.get("tczf") + "");
        // 添加主要诊断
        for (YbZyDisDiag zd : zdList) {
            // 选择第一诊断作为主诊断
            if(zd.getDisDiagNo() == 1){
                String code = zd.getDisDiag();
                map.put("zdmc", zd.getDisDiagComment());
                map.put("zdbm", code);
                BigDecimal fz = selectDiagScore(code, zyh, times);

                if(fz.compareTo(BigDecimal.ZERO) == 0){
                    // 无对照分值计算：统筹支付/分值标准
                    fz = DecimalUtil.divide(tczf, csbz, 1);
                    map.put("sblx", "无对照");
                } else {
                    map.put("sblx", "有对照");
                }
                // 计算预计支付
                BigDecimal yjzf = DecimalUtil.multiply(fz, jsbz);
                map.put("yjzf", yjzf);
                map.put("score", fz);
                map.put("bal", DecimalUtil.minus(yjzf, tczf));

                if(tczf.compareTo(BigDecimal.ZERO) == 0){
                    map.put("yjzf", 0);
                    map.put("score", 0);
                    map.put("bal", 0);
                    map.put("sblx", "非正常数据");
                }

                break;
            }
        }

        // 添加主要操作手术
        if(ba4List.size() > 0){
            for (BatjBa4 ss : ba4List) {
                if(ss.getSsxh() == 1){
                    map.put("ssbm", ss.getSsbm());
                    map.put("ssmc", ss.getSsmc());
                    break;
                }
            }
        }

    }

}
