package thyyxxk.webserver.service.medicalinsurance;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import thyyxxk.webserver.config.exception.BizException;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.constants.GetDateFormat;
import thyyxxk.webserver.constants.Message;
import thyyxxk.webserver.constants.sidicts.*;
import thyyxxk.webserver.dao.his.inpatient.DismissDao;
import thyyxxk.webserver.dao.his.medicalinsurance.SiLogDao;
import thyyxxk.webserver.dao.his.medicalinsurance.SiQueryDao;
import thyyxxk.webserver.dao.his.medicalinsurance.UpIdCollectionDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.datamodify.GetDropdownBox;
import thyyxxk.webserver.entity.datamodify.TYbSetModifyTime;
import thyyxxk.webserver.entity.datamodify.TYbSetlModifyReq;
import thyyxxk.webserver.entity.medicalinsurance.inpatient.BatjBa4;
import thyyxxk.webserver.entity.medicalinsurance.inpatient.YbZyDisDiag;
import thyyxxk.webserver.entity.medicalinsurance.inpatient.ZyDisDiagYb;
import thyyxxk.webserver.entity.medicalinsurance.inpatient.ZyInactpatient;
import thyyxxk.webserver.entity.medicalinsurance.log.SiLog;
import thyyxxk.webserver.entity.medicalinsurance.query.SiSetlFeeDetl;
import thyyxxk.webserver.entity.medicalinsurance.setllistupld.*;
import thyyxxk.webserver.entity.medicalinsurance.setllistupldTemp.*;
import thyyxxk.webserver.entity.querydata.JieSuanDanChaXun;
import thyyxxk.webserver.entity.querydata.SiSetlinfoTemp;
import thyyxxk.webserver.entity.querydata.TAutoUploadBill;
import thyyxxk.webserver.service.PublicServer;
import thyyxxk.webserver.service.casefrontsheet.CaseFrontSheetMainService;
import thyyxxk.webserver.service.redislike.RedisLikeService;
import thyyxxk.webserver.service.wxapi.SendWxInfoService;
import thyyxxk.webserver.utils.*;
import thyyxxk.webserver.websocket.WebSocketServer;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description: 医保管理服务，包涵项目对照等
 * @author: xc
 * @create: 2021/6/2914:44
 */
@Service
@Slf4j
@DS("his")
public class SetlListUpldService {

    private static final int NOT_UPLOADED = 1;
    private static final int UPLOADED = 2;
    private static final int All = 4;

    private static final String TOTAL_AMOUNT_CODE = "99";

    private static final String RESULT_CODE = "infcode";
    private static final String ERROR_MESSAGE = "err_msg";
    private static final String OUTPUT = "output";
    private final ExecService exec;
    private final SiQueryDao queryDao;
    private final UpIdCollectionDao dao;
    private final DismissDao dismissDao;
    private final PublicServer publicServer;
    private final SendWxInfoService sendWxInfoService;
    private final SiLogDao logDao;
    private final CaseFrontSheetMainService caseFrontSheetMainService;
    private final RedisLikeService redisLikeService;

    public SetlListUpldService(ExecService exec, SiQueryDao queryDao, UpIdCollectionDao upIdCollectionDao, DismissDao dismissDao, PublicServer publicServer, SendWxInfoService sendWxInfoService, SiLogDao logDao, CaseFrontSheetMainService caseFrontSheetMainService, RedisLikeService redisLikeService) {
        this.exec = exec;
        this.queryDao = queryDao;
        this.dao = upIdCollectionDao;
        this.dismissDao = dismissDao;
        this.publicServer = publicServer;
        this.sendWxInfoService = sendWxInfoService;
        this.logDao = logDao;
        this.caseFrontSheetMainService = caseFrontSheetMainService;
        this.redisLikeService = redisLikeService;
    }


    /**
     * 上传到医保的结算单上传
     *
     * @param patNo    住院号
     * @param times    住院次数
     * @param ledgerSn 账页号
     * @return 返回体术
     * @throws Exception 错误
     */
    public ResultVo<String> upldSetlList(String patNo, Integer times, Integer ledgerSn) throws Exception {
        ResultVo<UpldCollection> upldCollection = getUploadInfo(patNo, times, ledgerSn);
        if (upldCollection.getCode() != 200) {
            throw new BizException(ExceptionEnum.INTERNAL_SERVER_ERROR, upldCollection.getMessage());
        }
        if (!patNo.startsWith("JT") && patNo.indexOf("-") == 0) {
            if (StringUtil.isBlank(upldCollection.getData().getSetlinfo().getConerName())) {
                throw new BizException(ExceptionEnum.INTERNAL_SERVER_ERROR, "患者联系人姓名不能为空。");
            }

        }
        if (ListUtil.notBlank(upldCollection.getData().getOprninfo())) {
            for (OprninfoUpld item : upldCollection.getData().getOprninfo()) {
                if (StringUtil.isBlank(item.getOperDrCode())) {
                    throw new BizException(ExceptionEnum.INTERNAL_SERVER_ERROR, String.format("医生：【%s】，没有医保编码请去职工字典数据维护中添加", null == item.getOperDrName() ? "没有填写医生" : item.getOperDrName()));
                }
                if (StringUtil.notBlank(item.getAnstDrName()) && StringUtil.isBlank(item.getAnstDrCode())) {
                    throw new BizException(ExceptionEnum.INTERNAL_SERVER_ERROR, String.format("医生：【%s】，没有医保编码请去职工字典数据维护中添加", null == item.getAnstDrName() ? "没有填写医生" : item.getAnstDrName()));
                }
            }
        }
        JSONObject input = new JSONObject();
        input.put("setlinfo", JSONObject.parseObject(JSONObject.toJSONStringWithDateFormat(upldCollection.getData().getSetlinfo(), "yyyy-MM-dd HH:mm:ss")));
        input.put("payinfo", JSONArray.parseArray(JSONArray.toJSONString(upldCollection.getData().getPayinfo())));
        input.put("iteminfo", JSONArray.parseArray(JSONArray.toJSONString(upldCollection.getData().getIteminfo())));
        input.put("opspdiseinfo", JSONArray.parseArray(JSONArray.toJSONString(upldCollection.getData().getOpspdiseinfo())));
        input.put("diseinfo", JSONArray.parseArray(JSONArray.toJSONString(upldCollection.getData().getDiseinfo())));
        input.put("oprninfo", JSONArray.parseArray(JSONArray.toJSONString(upldCollection.getData().getOprninfo())));
        input.put("icuinfo", JSONArray.parseArray(JSONArray.toJSONString(upldCollection.getData().getIcuinfo())));
        input.put("bldinfo", JSONArray.parseArray(JSONArray.toJSONString(upldCollection.getData().getBldinfo())));
        JSONObject jsonObject = exec.makeTradeHeaderWithInsureArea(SiFunction.UPLOAD_SI_SETTLE_INFO, upldCollection.getData().getSetlinfo().getInsuplc());
        jsonObject.replace("input", input);
        // 这里是上传
        JSONObject result = exec.executeTrade(jsonObject, SiFunction.UPLOAD_SI_SETTLE_INFO);

        log.info("医保结算信息上传 \n操作人：{}\n参数：{} \n结果：{}", TokenUtil.getTokenUserId(), jsonObject, result);
        if (null == result) {
            return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
        }
        Integer infcode = result.getInteger(RESULT_CODE);
        logDao.insert(new SiLog(jsonObject, result, patNo, times, ledgerSn, infcode, null));
        if (null == infcode) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("医保中心报错：【%s】 ", result.getString("message")));
        }
        if (infcode == 0) {
            dao.fanHuiLiuShuiHao(result.getJSONObject(OUTPUT).getString("setl_list_id"), upldCollection.getData().getSetlinfo().getSetlId());
            return ResultVoUtil.success(ExceptionEnum.SUCCESS, "上传成功");
        }
        String errMsg = result.getString("err_msg");
        if (errMsg.length() > 9999) {
            errMsg = "字符超长自动截取" + errMsg.substring(0, 9999);
        }
        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("医保中心报错的：【%s】 ", errMsg));
    }

    /**
     * 获取上传到医保的信息
     *
     * @param patNo    住院号
     * @param times    住院次数
     * @param ledgerSn 账页号
     * @return 返回上传的结算单信息
     * @throws Exception 错误
     */
    public ResultVo<UpldCollection> getUploadInfo(String patNo, Integer times, Integer ledgerSn) throws Exception {
        boolean shiFouQianShouBingAn = dao.shiFouQianShou(patNo, times) > 0;
        if (ledgerSn == 0) {
            return outpatInformation(patNo, times, ledgerSn);
        }
        if (!patNo.startsWith("JT")) {
            if (!shiFouQianShouBingAn) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "该病案没有签收，请病案室签收后上传。");
            }
        }
        String medType = dao.getMedicalCategory(patNo, times, ledgerSn);
        boolean isFertilitySign = false;
        if (StringUtil.notBlank(medType)) {
            String[] giveBirth = new String[]{"2106", "2017", "52", "51"};
            if (Arrays.asList(giveBirth).contains(medType)) {
                isFertilitySign = true;
            }
        }

        Integer flag = dao.setlModifyReqAuditFlag(patNo, times);
        flag = flag == null ? 0 : flag;
        // 患者基本信息
        SetlinfoUpld setlinfoUpld = dao.setlinfo1(patNo, times, ledgerSn);
        EntityCopy.Copy(dao.setlinfo2(patNo, times), setlinfoUpld);
        EntityCopy.Copy(dao.setlinfo3(String.format("inpatient_no ='%s'", patNo)), setlinfoUpld);
        EntityCopy.Copy(dao.setlinfo4(patNo, times), setlinfoUpld);
        EntityCopy.Copy(dao.setlinfo5(patNo, times, ledgerSn), setlinfoUpld);

        if (patNo.startsWith("JT")) {
            EntityCopy.Copy(dao.singleDiseasePatientInformation(patNo, times), setlinfoUpld);
        }

        if (StringUtil.isBlank(setlinfoUpld.getSetlId())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "结算id为空");
        }
        // 特级护理
        setlinfoUpld.setSpgaNurscareDays(String.valueOf(dao.teJiHuLi(publicServer.getInpatientNo(patNo), times, ledgerSn, publicServer.getInfantFlag(patNo))));
        // 一级护理
        setlinfoUpld.setLv1NurscareDays(String.valueOf(dao.yiJiHuLi(publicServer.getInpatientNo(patNo), times, ledgerSn, publicServer.getInfantFlag(patNo))));
        // 二级护理
        setlinfoUpld.setScdNurscareDays(String.valueOf(dao.erJiHuLi(publicServer.getInpatientNo(patNo), times, ledgerSn, publicServer.getInfantFlag(patNo))));
        // 三级护理
        setlinfoUpld.setLv3NurscareDays(String.valueOf(dao.sanJiHuLi(publicServer.getInpatientNo(patNo), times, ledgerSn, publicServer.getInfantFlag(patNo))));
        GetDropdownBox getDropdownBox = dao.userInfo(TokenUtil.getTokenUserId());
        // 医疗机构填报人
        setlinfoUpld.setMedinsFillPsn(getDropdownBox.getName());
        // 医疗机构填报部门
        setlinfoUpld.setMedinsFillDept(getDropdownBox.getDeptName());
        // 医保机构经办人
        List<OprninfoUpld> oprninfoUpld = dao.oprninfoUplds(patNo, times, flag == 1 ? "batj_ba4_modify" : "batj_ba4");
        // 手术计数
        setlinfoUpld.setOprnOprtCodeCnt(String.valueOf(oprninfoUpld.size()));

        for (int i = 0; i < oprninfoUpld.size(); i++) {
            // 手术操作类别
            oprninfoUpld.get(i).setOprnOprtType(i == 0 ? "1" : "2");
        }

        // 离院方式 我们是从 0 开始的所以要加 1
        setlinfoUpld.setDscgWay(DecimalUtil.add1(setlinfoUpld.getDscgWay(), "1"));
        // 治疗类别 我们是从 0 开始的所以要加 1
        setlinfoUpld.setTrtType(DecimalUtil.add1(setlinfoUpld.getTrtType(), "1"));
        // 长沙总控的都传这个
        setlinfoUpld.setHsorg("长沙市医疗保障事务中心");
        setlinfoUpld.setHsorgOpter("长沙市医疗保障事务中心");
        // 因为我们是三级医院 所以就是三
        setlinfoUpld.setHiSetlLv("3");

        String setlId = setlinfoUpld.getSetlId();
        List<IteminfoUpld> amtAndOthAmt = dao.totalCost(setlId);
        if (ListUtil.isBlank(amtAndOthAmt)) {
            ResultVo<String> chrgitems = getChrgitems(patNo, setlId, setlinfoUpld.getMdtrtId(), setlinfoUpld.getInsuplc());
            if (chrgitems.getCode() != 200) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, chrgitems.getMessage());
            }
        }
        // 票据代码
        setlinfoUpld.setBillNo(dao.billNo(patNo, times, ledgerSn));
        setlinfoUpld.setBillCode("143001913350");
        setlinfoUpld.setBizSn(SnowFlakeId.instance().nextId());
        // 甲类费用
        Map<String, IteminfoUpld> jiaLeiFeiYong = dao.aAndBFees(setlId, "01", "claaSumfee").stream().collect(Collectors.toMap(IteminfoUpld::getMedChrgitm, a -> a, (k1, k2) -> k1));
        // 乙类费用
        Map<String, IteminfoUpld> yiLeiFeiYong = dao.aAndBFees(setlId, "02", "clabAmt").stream().collect(Collectors.toMap(IteminfoUpld::getMedChrgitm, a -> a, (k1, k2) -> k1));
        // 自费
        Map<String, IteminfoUpld> fulamtOwnpayAmt = dao.patientPays(setlId).stream().collect(Collectors.toMap(IteminfoUpld::getMedChrgitm, a -> a, (k1, k2) -> k1));
        if (ListUtil.notBlank(amtAndOthAmt)) {
            for (IteminfoUpld item : amtAndOthAmt) {
                String key = item.getMedChrgitm();
                if (jiaLeiFeiYong.containsKey(key)) {
                    item.setClaaSumfee(jiaLeiFeiYong.get(key).getClaaSumfee());
                }
                if (yiLeiFeiYong.containsKey(key)) {
                    item.setClabAmt(yiLeiFeiYong.get(key).getClabAmt());
                }
                if (fulamtOwnpayAmt.containsKey(key)) {
                    item.setFulamtOwnpayAmt(fulamtOwnpayAmt.get(key).getFulamtOwnpayAmt());
                }
                String a = DecimalUtil.minus(item.getAmt(), item.getClaaSumfee());
                a = DecimalUtil.minus(a, item.getClabAmt());
                a = DecimalUtil.minus(a, item.getFulamtOwnpayAmt());
                if (BigUtils.bigXiaoYu(new BigDecimal(a), 0)) {
                    item.setOthAmt("0.00");
                } else {
                    item.setOthAmt(a);
                }
                if (isFertilitySign) {
                    item.setFulamtOwnpayAmt(DecimalUtil.add(item.getFulamtOwnpayAmt(), item.getOthAmt()));
                    item.setOthAmt("0.00");
                }
            }
        }
        // 重症监护时间
        List<IcuinfoUpld> zhongZhenJianHu = getIcuinfoUplds(patNo, times);
        List<PayinfoUpld> payinfo = dao.payinfoUpld(patNo, times, ledgerSn);

        List<DiseinfoUpld> diseinfos = dao.diseinfo(patNo, times, flag == 1 ? "zy_dis_diag_yb_modify" : "zy_dis_diag_yb");
        setlinfoUpld.setDiagCodeCnt(String.valueOf(diseinfos.size()));

        for (int i = 0; i < diseinfos.size(); i++) {
            diseinfos.get(i).setMaindiagFlag(i == 0 ? "1" : "0");
        }
        // 新生儿入院类型写死为1
        if (StringUtil.notBlank(setlinfoUpld.getNwbBirWt())) {
            setlinfoUpld.setNwbAdmType("1");
        }
        // 如果是生育住院的那么 医保支付方式 为 1 按项目
        if (isFertilitySign) {
            setlinfoUpld.setHiPaymtd("1");
        }
        //  如果是 职工基本医疗保险的话 没有单位名称和地址 那么就 写死成 普通职工 和 现住址
        if ("310".equals(setlinfoUpld.getHiType())) {
            if (StringUtil.isBlank(setlinfoUpld.getEmpAddr())) {
                setlinfoUpld.setEmpAddr(setlinfoUpld.getCurrAddr());
            }
            if (StringUtil.isBlank(setlinfoUpld.getEmpName())) {
                setlinfoUpld.setEmpName("普通职工");
            }
        }

        // 呼吸机使用时长
        Integer ventUsedDura = dao.ventilatorUseTime(patNo, times);
        if (ventUsedDura != null) {
            setlinfoUpld.setVentUsedDura(secondsToTime(ventUsedDura));
        }

        UpldCollection upldCollection = new UpldCollection();
        // 患者的基本信息
        upldCollection.setSetlinfo(setlinfoUpld);
        //  基金支付信息
        upldCollection.setPayinfo(payinfo);
        // 门特慢特病诊断信息
        upldCollection.setOpspdiseinfo(dao.diagnosisOfMenterSDisease(patNo, times, ledgerSn));
        // 住院诊断信息
        upldCollection.setDiseinfo(diseinfos);
        //  收费项目信息
        upldCollection.setIteminfo(amtAndOthAmt);
        // 手术操作信息
        upldCollection.setOprninfo(oprninfoUpld);
        // 重症监护信息
        upldCollection.setIcuinfo(zhongZhenJianHu);
        // 输血信息
        List<PatientBldInfo> patientBldInfos = dao.shuXueXinXi(patNo, times);
        upldCollection.setBldinfo(new ArrayList<>());
        patientBldInfos.forEach((item) -> {
            Bldinfo bldinfo = new Bldinfo();
            bldinfo.setBldCat(item.getBldCat()).setBldAmt(item.getBldAmt().toString()).setBldUnt(item.getBldUnit());
            upldCollection.getBldinfo().add(bldinfo);
        });

        // 医保统筹基金支付	要减去 本院垫付
        String advancePaidByTheHospital = dao.advancePaidByTheHospital(patNo, times, ledgerSn);
        if (advancePaidByTheHospital != null) {
            upldCollection.getSetlinfo().setFundPaySumamt(DecimalUtil.minus(upldCollection.getSetlinfo().getFundPaySumamt(), advancePaidByTheHospital));
        }
        // 医疗类别为 生育
        List<String> birth = Arrays.asList("51", "52", "2106", "2107");

        if (birth.contains(medType)) {
            // 生育类别不需要下面的这些
            upldCollection.getSetlinfo().setNwbAge(null);
            upldCollection.getSetlinfo().setNwbAdmType(null);
        }

        return ResultVoUtil.success(upldCollection);
    }

    @NotNull
    private List<IcuinfoUpld> getIcuinfoUplds(String patNo, Integer times) {
        List<IcuinfoUpld> zhongZhenJianHu = new ArrayList<>();
        List<Date> zhuanKeShiJian = dao.zhuanKeShiJian(patNo, times);
        if (ListUtil.notBlank(zhuanKeShiJian)) {
            List<List<Date>> fenGeJianHuShiJian = ListUtils.partition(zhuanKeShiJian, 2);
            for (List<Date> dateList : fenGeJianHuShiJian) {
                long diff;
                Date inpoolTime;
                Date exitTime;
                if (dateList.size() == 2) {
                    inpoolTime = dateList.get(0);
                    exitTime = dateList.get(1);
                    diff = dateList.get(1).getTime() - dateList.get(0).getTime();
                } else {
                    Date chuYuanShiJian = dismissDao.selectActOrderDisDate(patNo, times);
                    if (chuYuanShiJian == null) {
                        chuYuanShiJian = dismissDao.selectActOrderDisDate2(patNo, times);
                    }
                    inpoolTime = dateList.get(0);
                    exitTime = chuYuanShiJian;
                    diff = chuYuanShiJian.getTime() - dateList.get(0).getTime();
                }
                long days = diff / (1000 * 60 * 60 * 24); // 天
                long hours = (diff - days * (1000 * 60 * 60 * 24)) / (1000 * 60 * 60); // 小时
                long minutes = (diff - days * (1000 * 60 * 60 * 24) - hours * (1000 * 60 * 60)) / (1000 * 60); // 分钟
                String zhongZhengJianHuShiJian = days + "/" + hours + "/" + minutes;
                IcuinfoUpld icuinfoUpld = new IcuinfoUpld();
                icuinfoUpld.setScsCutdWardType("ICU");
                icuinfoUpld.setScsCutdInpoolTime(inpoolTime);
                icuinfoUpld.setScsCutdExitTime(exitTime);
                icuinfoUpld.setScsCutdSumDura(zhongZhengJianHuShiJian);
                zhongZhenJianHu.add(icuinfoUpld);
            }
        }
        return zhongZhenJianHu;
    }


    /**
     * 这里是获取打印结算单的信息，需要重新分装一下
     *
     * @param patNo    住院号
     * @param times    住院次数
     * @param ledgerSn 账页号
     * @return 返回信息
     * @throws Exception 克隆可能会报错
     */
    public ResultVo<UpldCollectionTemp> daYingShangChuanJieSuanDan(String patNo, Integer times, Integer ledgerSn) throws
            Exception {
        Integer flag = dao.setlModifyReqAuditFlag(patNo, times);
        flag = null == flag ? 0 : flag;
        // 查询出来的信息
        ResultVo<UpldCollection> uploadInfo = getUploadInfo(patNo, times, ledgerSn);
        if (!uploadInfo.getCode().equals(ExceptionEnum.SUCCESS.getCode())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, uploadInfo.getMessage());
        }
        // 重新封装信息
        UpldCollectionTemp temp = new UpldCollectionTemp();

        // 患者基本信息
        temp.setSetlinfo(EntityCopy.Copy(uploadInfo.getData().getSetlinfo(), SetlinfoUpldTemp.class));
        temp.getSetlinfo().setSetlListId(dao.billingListSerialNumber(patNo, times, ledgerSn));
        //城乡居民 和 城镇职工  生育基金 不显示 上传需要，打印不需要
        // 390100 和  310100 和  510100 不显示
        List<String> printWithoutDisplay = Arrays.asList("390100", "310100", "510100");
        uploadInfo.getData().getPayinfo().removeIf(item -> printWithoutDisplay.contains(item.getFundPayType()));
        temp.setPayinfo(EntityCopy.CopyList(uploadInfo.getData().getPayinfo(), PayinfoUpldTemp.class));
        //  门诊慢特病
        temp.setOpspdiseinfo(EntityCopy.CopyList(uploadInfo.getData().getOpspdiseinfo(), OpspdiseinfoUpldTemp.class));
        // 诊断 有申请且成功的 就用 新的诊断
        temp.setDiseinfo(EntityCopy.CopyList(dao.zhenDuanXinXi(patNo, times, flag == 1 ? "zy_dis_diag_yb_modify" : "zy_dis_diag_yb"), DiseinfoUpldTemp.class));
        // 费用类型
        temp.setIteminfo(EntityCopy.CopyList(uploadInfo.getData().getIteminfo(), IteminfoUpldTemp.class));
        // 计算费用的总和
        IteminfoUpldTemp heJi = new IteminfoUpldTemp();
        if (ListUtil.notBlank(temp.getIteminfo())) {
            temp.setIteminfo(setMedType(temp.getIteminfo()));
            if (ledgerSn > 0) {
                for (IteminfoUpldTemp item : temp.getIteminfo()) {
                    heJi.setMedChrgitm(TOTAL_AMOUNT_CODE);

                    heJi.setAmt(DecimalUtil.add(heJi.getAmt(), item.getAmt()));

                    heJi.setClaaSumfee(DecimalUtil.add(heJi.getClaaSumfee(), item.getClaaSumfee()));

                    heJi.setClabAmt(DecimalUtil.add(heJi.getClabAmt(), item.getClabAmt()));

                    heJi.setFulamtOwnpayAmt(DecimalUtil.add(heJi.getFulamtOwnpayAmt(), item.getFulamtOwnpayAmt()));

                    heJi.setOthAmt(DecimalUtil.add(heJi.getOthAmt(), item.getOthAmt()));
                }
                temp.getIteminfo().add(heJi);
            }
        }

        // 手术 也是一样的
        temp.setOprninfo(EntityCopy.CopyList(dao.shouShuXinXi(patNo, times, flag == 1 ? "batj_ba4_modify" : "batj_ba4"), OprninfoUpldTemp.class));

        temp.setIcuinfo(EntityCopy.CopyList(uploadInfo.getData().getIcuinfo(), IcuinfoUpldTemp.class));
        // 国籍
        temp.getSetlinfo().setNtlyName(dao.getNtlyName(temp.getSetlinfo().getNtly()));
        // 民族
        temp.getSetlinfo().setNatyName(dao.getNatyName(temp.getSetlinfo().getNaty()));
        // 新生儿入院类型
        temp.getSetlinfo().setNwbAdmTypeName(StringUtil.isBlank(temp.getSetlinfo().getNwbAdmType()) ? "" : "正常新生儿");
        //患者证件类型
        temp.getSetlinfo().setPatnCertTypeName(dao.getPatnCertTypeName(temp.getSetlinfo().getPatnCertType()));
        // 职业
        temp.getSetlinfo().setPrfsName(dao.getPrfsName(temp.getSetlinfo().getPrfs()));
        // 与患者的关系
        temp.getSetlinfo().setPatnRltsName(dao.getPatnRltsName(temp.getSetlinfo().getPatnRlts()));
        // 医保类型
        temp.getSetlinfo().setHiTypeName(MdcsType.getName(temp.getSetlinfo().getHiType()));
        // 特殊人员类型
        temp.getSetlinfo().setSpPsnTypeName(PsnIdetType.getName(temp.getSetlinfo().getSpPsnType()));
        // 参保地
        temp.getSetlinfo().setInsuplcName(redisLikeService.getRegionName(temp.getSetlinfo().getInsuplc()));
        //入院科别
        temp.getSetlinfo().setAdmCatyName(dao.getYbDeptName(temp.getSetlinfo().getAdmCaty()));
        // 转科科别
        temp.getSetlinfo().setRefldeptDeptName(dao.getYbDeptName(temp.getSetlinfo().getRefldeptDept()));
        // 出院科别
        temp.getSetlinfo().setDscgCatyName(dao.getYbDeptName(temp.getSetlinfo().getDscgCaty()));

        log.info("数据:{}", JSON.toJSONString(temp));
        return ResultVoUtil.success(temp);
    }


    /**
     * 多个患者上传
     *
     * @param param 患者信息
     * @return 返回
     */
    public ResultVo<String> upldSetlListBatch(List<SiSetlinfoTemp> param) {
        if (ListUtil.isBlank(param)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请选择需要上传的患者。");
        }
        for (int i = 0; i < param.size(); i++) {
            SiSetlinfoTemp siPatInfo = param.get(i);
            try {
                ResultVo<String> resultVo = upldSetlList(siPatInfo.getPatNo(), siPatInfo.getTimes(), siPatInfo.getLedgerSn());
                upldSetlErrorMessage(siPatInfo.getPatNo(), siPatInfo.getTimes(), siPatInfo.getLedgerSn(), resultVo.getMessage(), resultVo.getCode() == 200 ? 0 : 1, i + 1, param.size(), siPatInfo.getOutDeptName(), siPatInfo.getPsnName(), siPatInfo.getReferPhysicianName());
            } catch (Exception e) {
                log.info("批量上传结算单错误：{}", JSON.toJSONString(e));
                e.printStackTrace();
                upldSetlErrorMessage(siPatInfo.getPatNo(), siPatInfo.getTimes(), siPatInfo.getLedgerSn(), e.getMessage(), 2, i + 1, param.size(), siPatInfo.getOutDeptName(), siPatInfo.getPsnName(), siPatInfo.getReferPhysicianName());
            }
        }
        return ResultVoUtil.success();
    }

    /**
     * 全部上传
     *
     * @return 返回信息
     */
    public ResultVo<String> upldSetlListTimes(JieSuanDanChaXun param) {
        try {
            param.setPageSize(param.getTotal());
            param.setCurrentPage(1);
            List<SiSetlinfoTemp> list = huoQuJieSuanRenYuan(param).getData().getRecords();
            if (ListUtil.isBlank(list)) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有要上传的信息。");
            }
            upldSetlListBatch(list);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("时间范围上传结算单错误：{}", JSON.toJSONString(e));
        }
        return ResultVoUtil.success();
    }

    /**
     * 发送医保上传的错误信息
     *
     * @param meg 错误消息
     */
    public void upldSetlErrorMessage(String patNo, Integer times, Integer ledgerSn, String meg, int type, int index,
                                     int total, String outDeptName, String psnName, String referPhysicianName) {
        JSONObject obj = new JSONObject();
        obj.put("psnName#患者姓名|1", psnName);
        obj.put("patNo#住院号|2", patNo);
        obj.put("times#住院次数|3", times);
        obj.put("ledgerSn#账页号|4", ledgerSn);
        obj.put("message#上传结果|5", meg.length() > 2000 ? meg.substring(0, 2000) : meg);
        obj.put("outDeptName#出院科室|6", outDeptName);
        obj.put("referPhysicianName#管床医生|7", referPhysicianName);
        obj.put("type#类型|8", type);
        obj.put("total", total);
        obj.put("index", index);
        obj.put("jdtType", "upload");
        obj.put("title", String.format("住院号：【%s】，住院次数：【%d】，账页号：【%d】。", patNo, times, ledgerSn));
        WebSocketServer.sendMessageByUserCode(TokenUtil.getTokenUserId(), SocketMsg.socketVo(Message.JDT_MESSAGE, obj));
        log.info("发送信息通知：{}", obj.toJSONString());
    }

    private ResultVo<String> getChrgitems(String patNo, String setlId, String mdtrtId, String admdvs) {
        JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.QUERY_FEE_DETAILS, admdvs);
        JSONObject data = new JSONObject();
        data.put("psn_no", queryDao.selectPsnNo(patNo));
        data.put("setl_id", setlId);
        data.put("mdtrt_id", mdtrtId);
        input.getJSONObject("input").put("data", data);
        JSONObject result = exec.executeTrade(input, SiFunction.QUERY_FEE_DETAILS);
        log.info("【操作员：{}】，【结算单上传】查询费用明细：\n参数：{}，\n结果：{}", TokenUtil.getTokenUserId(), input, result);
        if (null == result) {
            return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
        }
        if (null == result.getInteger(RESULT_CODE)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医保中心报错：" + result.getString("message"));
        }
        if (0 == result.getInteger(RESULT_CODE)) {
            JSONArray output = result.getJSONArray(OUTPUT);
            if (null == output || output.size() == 0) {
                return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST, "没有查询到费用明细。");
            }
            List<SiSetlFeeDetl> list = new ArrayList<>();
            for (int i = 0; i < output.size(); i++) {
                SiSetlFeeDetl fee = JSONObject.parseObject(output.getJSONObject(i).toJSONString(), SiSetlFeeDetl.class);
                if (StringUtil.isBlank(fee.getSetlId())) {
                    fee.setSetlId(setlId);
                }
                list.add(fee);
                if (list.size() == 30) {
                    queryDao.insertSetlFeeDetlBatch(list);
                    list.clear();
                }
            }
            if (list.size() > 0) {
                queryDao.insertSetlFeeDetlBatch(list);
            }
            return ResultVoUtil.success("查询成功。");
        }
        return ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, result.getString(ERROR_MESSAGE));
    }


    /**
     * 获取医保结算单信息
     *
     * @param param 参数
     * @return 返回数据
     */
    public ResultVo<IPage<SiSetlinfoTemp>> huoQuJieSuanRenYuan(JieSuanDanChaXun param) {
        IPage<SiSetlinfoTemp> page = new Page<>();
        page.setRecords(dao.huoQuJieSuanRenYuan(statementQueryConditions(param),
                param.getCurrentPage(), param.getPageSize()));
        if (ListUtil.isBlank(page.getRecords())) {
            return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
        }
        Set<String> inpatientNos = new HashSet<>();
        for (SiSetlinfoTemp item : page.getRecords()) {
            inpatientNos.add(item.getPatNo());
            item.setGendName("1".equals(item.getGend()) ? "男" : "女");
            if (item.getClrOptinsName() == null) {
                if ("439900".equals(item.getClrOptins())) {
                    item.setClrOptinsName("省本级");
                } else if ("430199".equals(item.getClrOptins())) {
                    item.setClrOptinsName("市本级");
                }
            }
            Insutype insutype = Insutype.get(item.getInsutype());
            if (null != insutype) {
                item.setInsutypeName(insutype.getName());
            }
            PsnType psnType = PsnType.get(item.getPsnType());
            if (null != psnType) {
                item.setPsnTypeName(psnType.getName());
            }
            MedType medType = MedType.get(item.getMedType());
            if (null != medType) {
                item.setMedTypeName(medType.getName());
            }
            item.setInsuplcAdmdvsName(redisLikeService.getRegionName(item.getInsuplcAdmdvs()));
        }
        Map<String, ZyDisDiagYb> zhuZhenDuanOld = dao.zhuZhenDuan(inpatientNos, "zy_dis_diag_yb").stream().collect(Collectors.toMap(item -> item.getInpatientNo() + item.getAdmissTimes(), a -> a, (k1, k2) -> k1));

        Map<String, ZyDisDiagYb> zhuZhenDuanNew = dao.zhuZhenDuan(inpatientNos, "zy_dis_diag_yb_modify").stream().collect(Collectors.toMap(item -> item.getInpatientNo() + item.getAdmissTimes(), a -> a, (k1, k2) -> k1));
        // 坑爹的 group by 会自动排序 ，这样就会导致根据，科室的编码来排序，而不是根据我的，转科情况来排序
        // 1、取出全部的数据
        List<SiSetlinfoTemp> zhuanKeShi = dao.zhuanKeKeShi(inpatientNos);
        // 2、重新 set 进去 这里要使用到 LinkedHashSet 因为这个是无序的，不然也会被盘排序
        Set<SiSetlinfoTemp> keShiSet = new LinkedHashSet<>(zhuanKeShi);
        // 3、 转map 然后 进行匹配
        Map<String, List<SiSetlinfoTemp>> zhuanKeMap = keShiSet.stream().collect(Collectors.groupingBy(item -> item.getPatNo() + item.getTimes()));
        for (SiSetlinfoTemp item : page.getRecords()) {
            String key = item.getPatNo() + item.getTimes();
            String zhuanKeKey = item.getPatNo() + item.getTimes();
            ZyDisDiagYb disOld = zhuZhenDuanOld.get(key);
            List<SiSetlinfoTemp> temp = zhuanKeMap.get(zhuanKeKey);
            if (disOld != null) {
                item.setDisDiag(disOld.getDisDiag());
                item.setDisDiagComment(disOld.getDisDiagComment());
            }
            ZyDisDiagYb disNew = zhuZhenDuanNew.get(key);
            if (disNew != null) {
                item.setDisDiag(disNew.getDisDiag());
                item.setDisDiagComment(disNew.getDisDiagComment());
            }
            if (ListUtil.notBlank(temp)) {
                item.setZhuanKeAmount(temp.size());
                if (temp.size() > 1) {
                    StringBuilder keShi = new StringBuilder();
                    for (SiSetlinfoTemp items : temp) {
                        if (!item.getPatNo().equals(items.getPatNo())) {
                            keShi = new StringBuilder();
                        }
                        if (keShi.length() != 0) {
                            keShi.append("--->");
                        }
                        item.setZhuanKeName(keShi.append(items.getWardCodeName()));
                    }
                }
            }
        }
        if (param.getTotal() == 0) {
            page.setTotal(dao.huoQuJieSuanRenYuanTotal(param.getStartTime(), param.getEndTime(), param.getClrType(), param.getPatNo(), param.getInsutype(), param.getOutDept(), param.getMedType(), param.getPsnType(), param.getClrOptins(), param.getDecTypes(), param.getFlag(), param.getReferPhysician(), param.getAuditFlag(), param.getHiPaymtd()));
        }
        return ResultVoUtil.success(page);
    }

    /**
     * 结算单上传条件查询
     *
     * @param param 参数
     * @return 返回
     */
    private QueryWrapper<?> statementQueryConditions(JieSuanDanChaXun param) {
        QueryWrapper<?> qw = new QueryWrapper<>();
        log.info("查询参数:{}", JSON.toJSONString(param));
        if (StringUtil.notBlank(param.getStartTime())) {
            qw.ge("a.setl_time", param.getStartTime());
            qw.le("a.setl_time", param.getEndTime());
        }
        if (StringUtil.notBlank(param.getClrType())) {
            qw.eq("a.setl_type", param.getClrType());
        }
        if (StringUtil.notBlank(param.getPatNo())) {
            qw.eq("a.pat_no", param.getPatNo());
        }
        if (ListUtil.notBlank(param.getInsutype())) {
            qw.in("insutype", param.getInsutype());
        }
        if (ListUtil.notBlank(param.getOutDept())) {
            qw.in("isnull(zk_ward,small_dept)", param.getOutDept());
        }
        if (ListUtil.notBlank(param.getMedType())) {
            qw.in("a.med_type", param.getMedType());
        }
        if (ListUtil.notBlank(param.getInsuplcAdmdvs())) {
            qw.in("insuplc_admdvs", param.getInsuplcAdmdvs());
        }
        if (ListUtil.notBlank(param.getPsnType())) {
            qw.in("psn_type", param.getPsnType());
        }
        if (ListUtil.notBlank(param.getDecTypes())) {
            qw.in("b.dec_type", param.getDecTypes());
        }
        if (ListUtil.notBlank(param.getClrOptins())) {
            qw.in("clr_optins", param.getClrOptins());
        }
        if (param.getFlag() == NOT_UPLOADED) {
            qw.isNull("a.setl_list_id");
        } else if (param.getFlag() == UPLOADED) {
            qw.isNotNull("a.setl_list_id");
        }
        if (param.getAuditFlag() != All) {
            qw.eq("c.audit_flag", param.getAuditFlag());
        }
        if (param.getHiPaymtd() != null && param.getHiPaymtd() != 0) {
            qw.eq("a.hi_paymtd", param.getHiPaymtd());
        }
        if (StringUtil.notBlank(param.getReferPhysician())) {
            qw.eq("b.refer_physician", param.getReferPhysician());
        }
        return qw;
    }

    public String secondsToTime(int seconds) {
        int day;
        int hour;
        int minute;
        day = seconds / (24 * 60 * 60);
        seconds -= day * 24 * 60 * 60;
        hour = seconds / (60 * 60);
        seconds -= hour * 60 * 60;
        minute = seconds / 60;
        return day + "/" + hour + "/" + minute;
    }

    /**
     * 获取 医疗类别
     *
     * @return 返回   code name
     */
    public ResultVo<List<Object>> getMedType() {
        JSONArray jsonArray = new JSONArray();
        for (MedType e : MedType.values()) {
            JSONObject object = new JSONObject();
            object.put("code", e.getCode());
            object.put("name", e.getName());
            jsonArray.add(object);
        }
        return ResultVoUtil.success(jsonArray);
    }

    public List<IteminfoUpldTemp> setMedType(List<IteminfoUpldTemp> item) {
        Map<String, IteminfoUpldTemp> map = new HashMap<>(item.size());
        for (IteminfoUpldTemp upldTemp : item) {
            String key = upldTemp.getMedChrgitm();
            if (map.containsKey(key)) {
                IteminfoUpldTemp it1 = new IteminfoUpldTemp();
                it1.setAmt(DecimalUtil.add(map.get(key).getAmt(), upldTemp.getAmt()));
                it1.setClaaSumfee(DecimalUtil.add(map.get(key).getClaaSumfee(), upldTemp.getClaaSumfee()));
                it1.setClabAmt(DecimalUtil.add(map.get(key).getClabAmt(), upldTemp.getClabAmt()));
                it1.setFulamtOwnpayAmt(DecimalUtil.add(map.get(key).getFulamtOwnpayAmt(), upldTemp.getFulamtOwnpayAmt()));
                it1.setOthAmt(DecimalUtil.add(map.get(key).getOthAmt(), upldTemp.getOthAmt()));
                it1.setMedChrgitm(key);
                map.replace(key, it1);
            } else {
                map.put(key, upldTemp);
            }
        }
        List<IteminfoUpldTemp> newItem = new ArrayList<>();
        for (GetDropdownBox box : huoQuFeiYongMing()) {
            if (map.containsKey(box.getCode())) {
                newItem.add(map.get(box.getCode()));
            } else {
                IteminfoUpldTemp it = new IteminfoUpldTemp();
                it.setMedChrgitm(box.getCode());
                newItem.add(it);
            }
        }
        if (map.containsKey(TOTAL_AMOUNT_CODE)) {
            newItem.add(map.get(TOTAL_AMOUNT_CODE));
        }
        return newItem;
    }

    public List<GetDropdownBox> huoQuFeiYongMing() {
        List<GetDropdownBox> list = new ArrayList<>();
        for (MedChrgitmType e : MedChrgitmType.values()) {
            GetDropdownBox box = new GetDropdownBox();
            box.setCode(e.getCode());
            box.setName(e.getName());
            list.add(box);
        }
        return list;
    }

    /**
     * 获取 费用类型
     *
     * @return 返回费用
     */
    public ResultVo<List<Object>> getMedChrgitmType() {
        JSONArray jsonArray = new JSONArray();
        for (MedChrgitmType e : MedChrgitmType.values()) {
            JSONObject object = new JSONObject();
            object.put("code", e.getCode());
            object.put("name", e.getName());
            jsonArray.add(object);
        }
        return ResultVoUtil.success(jsonArray);
    }

    /**
     * 基金支付类型
     *
     * @return 返回基金code 和 name
     */
    public ResultVo<List<Object>> getFundPayType() {
        JSONArray jsonArray = new JSONArray();
        for (FundPayType e : FundPayType.values()) {
            JSONObject object = new JSONObject();
            object.put("code", e.getCode());
            object.put("name", e.getName());
            jsonArray.add(object);
        }
        return ResultVoUtil.success(jsonArray);
    }

    /**
     * 医保结算单上传导出 execl 表格
     *
     * @param response 返回
     * @param param    参数
     */
    public void exportExcel(HttpServletResponse response, JieSuanDanChaXun param) {
        param.setPageSize(100);
        int currentPage = (int) Math.ceil(param.getTotal() / (double) 100);
        List<SiSetlinfoTemp> list = new ArrayList<>();
        JSONObject obj = new JSONObject();
        obj.put("jdtType", "download");
        obj.put("jdtTitle", "导出Excel");
        obj.put("total", param.getTotal());
        for (int i = 0; i < currentPage; i++) {
            param.setCurrentPage(i + 1);
            list.addAll(huoQuJieSuanRenYuan(param).getData().getRecords());
            obj.put("index", list.size());
            WebSocketServer.sendMessageByUserCode(TokenUtil.getTokenUserId(), SocketMsg.socketVo(Message.JDT_MESSAGE, obj));
        }
        String[] title = {"姓名", "审核状态", "申报类型", "出院科室", "住院号/门诊号", "性别",
                "住院天数", "诊断编码", "诊断名称", "治疗方式", "总费用", "报销金额",
                "险种类型", "人员类别", "结算时间", "医疗类别", "清算机构", "参保地",
                "管床医生", "转科室", "转科次数", "申请备注"};
        String[][] content = new String[list.size()][];
        for (int i = 0; i < list.size(); i++) {
            content[i] = new String[title.length];
            SiSetlinfoTemp pojo = list.get(i);
            content[i][0] = pojo.getPsnName();
            content[i][1] = pojo.getAuditFlagName();
            content[i][2] = pojo.getDecTypeName();
            content[i][3] = pojo.getOutDeptName();
            content[i][4] = pojo.getPatNo();
            content[i][5] = pojo.getGendName();
            content[i][6] = pojo.getActIptDays();
            content[i][7] = pojo.getDisDiag();
            content[i][8] = pojo.getDisDiagComment();
            content[i][9] = pojo.getOperationName();
            content[i][10] = pojo.getMedfeeSumamt();
            content[i][11] = pojo.getFundPaySumamt();
            content[i][12] = pojo.getInsutypeName();
            content[i][13] = pojo.getPsnTypeName();
            content[i][14] = DateUtil.formatDatetime(pojo.getSetlTime(), GetDateFormat.DATE_TIME);
            content[i][15] = pojo.getMedTypeName();
            content[i][16] = pojo.getClrOptinsName();
            content[i][17] = pojo.getInsuplcAdmdvsName();
            content[i][18] = pojo.getReferPhysicianName();
            content[i][19] = pojo.getZhuanKeName() == null ? "" : pojo.getZhuanKeName().toString();
            content[i][20] = pojo.getZhuanKeAmount() == null ? "" : pojo.getZhuanKeAmount().toString();
            content[i][21] = pojo.getReqRemark();
        }
        //传三个参数 一个是 固定的 response ，excel的头部信息，excel的内容
        ExcelUtil.exportExcel(response, title, content);
    }

    public ResultVo<ZyInactpatient> jieSuanDanKeXiuGaiXinXi(String patNo, Integer times, Integer ledgerSn) {
        SetlinfoUpld setlinfoUpld = dao.setlinfo1(patNo, times, ledgerSn);
        if (StringUtil.isBlank(setlinfoUpld.getSetlId())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "结算id为空");
        }
        ZyInactpatient zy = dao.huanZheXinXi(patNo, times);
        List<Integer> code = publicServer.getRoleCode().getData();
        if (!code.contains(1) && !code.contains(8)) {
            if (zy.getReferPhysician() == null || !zy.getReferPhysician().equals(TokenUtil.getTokenUserId())) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "您不是该患者的管床医生。");
            }
            TYbSetModifyTime modifyTime = dao.keXiuGaiShiJian();
            if (!DateUtil.isEffectiveDate(new Date(), modifyTime.getStartTime(), modifyTime.getEndTime())) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("当前不在医保科设置的修改时间范围内<br>开始时间：【%s】<br>结束时间：【%s】<br>这段结算时间范围内的患者可修改。", DateUtil.formatDatetime(modifyTime.getStartTime(), "yyyy-MM-dd"), DateUtil.formatDatetime(modifyTime.getEndTime(), "yyyy-MM-dd")));
            }
        }
        if (zy == null) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "未查询到患者信息。");
        }
        // 在这里带出 患者病案首页的 入院病情
        Map<String, YbZyDisDiag> zhenDuanMap = dao.huanZheBingAnShouYeZhenDuanRuYuanBingQing(patNo, times).stream().collect(Collectors.toMap(YbZyDisDiag::getDisDiag, a -> a, (k1, k2) -> k1));
        List<YbZyDisDiag> laoZhenDuan = dao.zhenDuanXinXi(patNo, times, "zy_dis_diag_yb");
        List<YbZyDisDiag> xuYaoGenXinDeZhenDuan = new ArrayList<>();

        for (YbZyDisDiag item : laoZhenDuan) {
            if (item.getAdmissCond() == null) {
                String key = item.getDisDiag();
                YbZyDisDiag yb = zhenDuanMap.get(key);
                if (yb != null && yb.getAdmissCond() != null) {
                    item.setAdmissCond(yb.getAdmissCond());
                    xuYaoGenXinDeZhenDuan.add(item);
                }
            }
        }
        if (ListUtil.notBlank(xuYaoGenXinDeZhenDuan)) {
            dao.genXingLaoZhenDuan(xuYaoGenXinDeZhenDuan);
        }
        // 新老一起查
        zy.setBatjBa4(dao.shouShuXinXi(patNo, times, "batj_ba4"));
        zy.setNewBatjBa4(dao.shouShuXinXi(patNo, times, "batj_ba4_modify"));
        // 诊断编码
        zy.setYbZyDisDiag(dao.zhenDuanXinXi(patNo, times, "zy_dis_diag_yb"));
        zy.setNewYbZyDisDiag(dao.zhenDuanXinXi(patNo, times, "zy_dis_diag_yb_modify"));

        zy.setPatientBldInfos(dao.shuXueXinXi(patNo, times));

        // todo 在这里要返回患者的分值和科室盈亏
        for (YbZyDisDiag item : zy.getYbZyDisDiag()) {
            item.setSsfz(caseFrontSheetMainService.fetchSsfz(item.getDisDiag().trim(), patNo, times).getData());
        }

        for (YbZyDisDiag item : zy.getNewYbZyDisDiag()) {
            item.setSsfz(caseFrontSheetMainService.fetchSsfz(item.getDisDiag().trim(), patNo, times).getData());
        }

        return ResultVoUtil.success(zy);
    }

    public ResultVo<IPage<GetDropdownBox>> shouShuBianMa(String content, long currentPage) {
        IPage<GetDropdownBox> page = new Page<>();
        page.setRecords(dao.searchSurgeryByAlpha(StringUtil.isContainChinese(content), currentPage));
        page.setTotal(dao.searchSurgeryTotal(StringUtil.isContainChinese(content)));
        return ResultVoUtil.success(page);
    }

    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> setlModifyReq(ZyInactpatient param) {
        param.setLedgerSn(publicServer.getLedgerSn(param.getInpatientNo(), param.getAdmissTimes()));
        Set<String> zhenDuanBianMa = new HashSet<>();
        for (YbZyDisDiag item : param.getYbZyDisDiag()) {
            if (item.getDisDiagNo() == null || item.getDisDiagNo() <= 0) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "诊断排序不能为空，且最小值为 1 。");
            }
            zhenDuanBianMa.add(item.getDisDiag());
            if (item.getNewData()) {
                item.setInpatientNo(param.getInpatientNo());
                item.setAdmissTimes(param.getAdmissTimes());
                item.setOpDiagDate(new Date());
                item.setOpIdCode(param.getOpIdCode());
            } else {
                if (StringUtil.isBlank(item.getDisDiag())) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请填写诊断。");
                }
                if (StringUtil.isBlank(item.getSiDiagType())) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "诊断类别不能为空。");
                }
                if (item.getAdmissCond() == null) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "入院病情不能为空。");
                }
            }
        }
        for (BatjBa4 item : param.getBatjBa4()) {
            if (item.getSsxh() == null || item.getSsxh() <= 0) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "手术排序不能为空，且最小值为 1。");
            }
            item.setZyh(param.getInpatientNo());
            item.setZycs(param.getAdmissTimes());
            if (!item.getNewData()) {
                if (item.getSsrq() == null) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "手术日期不能为空。");
                }
                if (StringUtil.isBlank(item.getSsys())) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "手术医生不能为空");
                }
                if (StringUtil.isBlank(item.getSsmc())) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "手术名称不能为空");
                }
                if (StringUtil.isBlank(item.getSsjb())) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "手术级别不能为空");
                }
                if (StringUtil.isBlank(item.getSsbm())) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "手术编码不能为空");
                }
                if (StringUtil.isBlank(item.getQkjb()) || StringUtil.isBlank(item.getYhqk())) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "切口愈合等级不能为空");
                }
                try {
                    PublicServer.surgeryTimeLimit(item.getOpStartDate(), item.getOpEndDate(), item.getAnstStartDate(), item.getAnstEndDate());
                } catch (BizException e) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "手术名称:【" + item.getSsmc() + "】" + e.getMessage());
                }
            }
        }
        param.getYbZyDisDiag().sort(Comparator.comparingInt(YbZyDisDiag::getDisDiagNo));
        param.getBatjBa4().sort(Comparator.comparingInt(BatjBa4::getSsxh));
        if (param.getYbZyDisDiag().size() != zhenDuanBianMa.size()) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "不可以有相同的诊断。");
        }
        dao.delReq(param.getInpatientNo(), param.getAdmissTimes());
        dao.setlModifyReq(param.getInpatientNo(), param.getAdmissTimes(), TokenUtil.getTokenUserId(), param.getOpIdName(), param.getReqRemark());
        if (ListUtil.notBlank(param.getYbZyDisDiag())) {
            dao.setlModDis(param.getYbZyDisDiag(), "zy_dis_diag_yb_modify");
        }
        if (ListUtil.notBlank(param.getBatjBa4())) {
            dao.setlModBat(param.getBatjBa4(), "batj_ba4_modify");
        }
        dao.shenBao(param.getOperation(), param.getDecType(), param.getInpatientNo(), param.getAdmissTimes());
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "申请成功，请等待医保科审核。");
    }

    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> setlUploadAudit(Integer id, Integer auditFlag, String remark, String auditStaff, String
            auditName) {
        TYbSetlModifyReq req = dao.shenHeXinXi(id);
        if (req == null) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有找到对应的信息，可能医生重新提交了,请刷新页面后重试。");
        } else if (req.getAuditFlag() != 0) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("该数据已被审核<br>审核人：【%s】<br>审核日期：【%s】", req.getAuditName(), DateUtil.formatDatetime(req.getAuditDate())));
        }
        dao.upAuditFlag(id, 3);
        if (auditFlag == 1) {
            // 审核通过需要 删除 并更新 现在占时用不到
//            dao.delYuanShuJu(req.getPatNo(), req.getTimes());
//            dao.auditTongGuo(req.getPatNo(), req.getTimes());
            dao.updateReq(id, remark, auditStaff, auditName);
            dao.upAuditFlag(id, auditFlag);
            return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "审核已通过 (*^▽^*)");
        }
        if (StringUtil.isBlank(remark)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "驳回信息不能为空。");
        }
        dao.upAuditFlag(id, auditFlag);
        sendWxInfoService.sendCorpWxMsg(dao.yuanGongGongHao(req.getReqOpId()), String.format("医保结算单上传\n申请已驳回\n患者姓名：【%s】\n住院号：【%s】\n原因：【%s】\n审核人：【%s】", req.getPatName(), req.getPatNo(), remark, auditName));
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "审核已驳回 (╯﹏╰)b");
    }

    public ResultVo<TYbSetModifyTime> xianZhiShiJian() {
        return ResultVoUtil.success(dao.xianZhiShiJian());
    }

    public ResultVo<String> sheZhiShiJian(String startTime, String endTime, String opId) {
        dao.sheZhiShiJian(startTime, endTime, opId);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "设置成功 (oﾟ▽ﾟ)o  ");
    }

    /**
     * 获取患者的科室费用
     *
     * @param patNo 住院号
     * @param times 住院次数
     * @return 返回费用
     */
    public ResultVo<List<Map<String, String>>> getHuanZheFeiYong(String patNo, Integer times) {
        return ResultVoUtil.success(dao.getHuanZheFeiYong(patNo, times));
    }

    public ResultVo<String> xiuGaiGuanChuangYiShen(String patNo, Integer times, String code) {
        if (StringUtil.isBlank(patNo) || times == null || times == 0) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "住院号或住院次数为空。");
        } else if (StringUtil.isBlank(code)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "管床医生不能设置为空。");
        }
        dao.xiuGaiGuanChaungYiShen(patNo, times, code);
        log.info("修改管床医生 ==》 修改人{}，住院号：{}，次数：{}，管床医生：{}", TokenUtil.getTokenUserId(), patNo, times, code);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "管床医生修改成功。");
    }

    private ResultVo<List<MzChargitems>> getmZChrgitems(String patNo, String setlId, String mdtrtId, String admdvs) {
        JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.QUERY_FEE_DETAILS, admdvs);
        JSONObject data = new JSONObject();
        data.put("psn_no", queryDao.selectPsnNo(patNo));
        data.put("setl_id", setlId);
        data.put("mdtrt_id", mdtrtId);
        input.getJSONObject("input").put("data", data);
        JSONObject result = exec.executeTrade(input, SiFunction.QUERY_FEE_DETAILS);
        if (null == result) {
            return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
        }
        if (null == result.getInteger(RESULT_CODE)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医保中心报错：" + result.getString("message"));
        }
        if (0 == result.getInteger(RESULT_CODE)) {
            JSONArray output = result.getJSONArray(OUTPUT);
            if (null == output || output.size() == 0) {
                return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST, "没有查询到费用明细。");
            }
            Map<String, MzChargitems> detailsOfMedicalInsuranceExpenses = new HashMap<>();
//            01	甲类	03	丙类 02	乙类	　	　
            for (int i = 0; i < output.size(); i++) {
                MzChargitems mzChargitems1 = new MzChargitems();
                DetailsOfMedicalInsuranceExpenses singleFee = EntityCopy.Copy(output.getJSONObject(i), DetailsOfMedicalInsuranceExpenses.class);
                if (detailsOfMedicalInsuranceExpenses.containsKey(singleFee.getMed_chrgitm_type())) {
                    MzChargitems mzChargitems = detailsOfMedicalInsuranceExpenses.get(singleFee.getMed_chrgitm_type());
                    switch (singleFee.getChrgitm_lv()) {
                        case "01":
                            mzChargitems.setClaaSumfee(DecimalUtil.add(singleFee.getDet_item_fee_sumamt(), mzChargitems.getClaaSumfee()));
                            break;
                        case "02":
                            mzChargitems.setClabAmt(DecimalUtil.add(singleFee.getDet_item_fee_sumamt(), mzChargitems.getClabAmt()));
                            break;
                        case "03":
                            mzChargitems.setOthAmt(DecimalUtil.add(singleFee.getDet_item_fee_sumamt(), mzChargitems.getOthAmt()));
                            break;
                        default:
                            break;
                    }
                    mzChargitems.setDetItemFeeSumamt(DecimalUtil.add(singleFee.getDet_item_fee_sumamt(), mzChargitems.getDetItemFeeSumamt()));
                    mzChargitems.setFulamtOwnpayAmt(DecimalUtil.add(singleFee.getFulamt_ownpay_amt(), mzChargitems.getFulamtOwnpayAmt()));
                } else {
                    switch (singleFee.getChrgitm_lv()) {
                        case "01":
                            mzChargitems1.setClaaSumfee(singleFee.getDet_item_fee_sumamt());
                            break;
                        case "02":
                            mzChargitems1.setClabAmt(singleFee.getDet_item_fee_sumamt());
                            break;
                        case "03":
                            mzChargitems1.setOthAmt(singleFee.getDet_item_fee_sumamt());
                            break;
                        default:
                            break;
                    }
                    mzChargitems1.setDetItemFeeSumamt(singleFee.getDet_item_fee_sumamt());
                    mzChargitems1.setMedChrgitmType(singleFee.getMed_chrgitm_type());
                    mzChargitems1.setFulamtOwnpayAmt(singleFee.getFulamt_ownpay_amt());
                    detailsOfMedicalInsuranceExpenses.put(singleFee.getMed_chrgitm_type(), mzChargitems1);
                }
            }
            return ResultVoUtil.success(new ArrayList<>(detailsOfMedicalInsuranceExpenses.values()));
        }
        return ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, result.getString(ERROR_MESSAGE));
    }

    public ResultVo<UpldCollection> outpatInformation(String patNo, Integer times, Integer ledgerSn) throws
            Exception {
        UpldCollection upldCollection = new UpldCollection();
        SetlinfoUpld mzPatient = dao.mzPatInfo(patNo, times);
        EntityCopy.Copy(dao.mzPatInfo1(patNo, times), mzPatient);
        EntityCopy.Copy(dao.mzJieSuanXinXi(patNo, times), mzPatient);

        upldCollection.setSetlinfo(mzPatient);
        mzPatient.setMedcasno(patNo + "_" + times);
        // 门诊慢特病
        OpspdiseinfoUpld opspdiseinfoUpld = dao.outpatientDiagnosis1(patNo, times);

        if (opspdiseinfoUpld != null) {
            String[] str = opspdiseinfoUpld.getDiagCode().split(",");
            List<OpspdiseinfoUpld> opspdiseinfoUpldList = new ArrayList<>();
            for (String s : str) {
                opspdiseinfoUpldList.add(dao.outpatientSlowDiagnosis(s));
            }
            upldCollection.setOpspdiseinfo(opspdiseinfoUpldList);
        } else {
            upldCollection.setOpspdiseinfo(dao.outpatientDiagnosis2(patNo, times));
        }


        mzPatient.setHsorg("长沙市医疗保障事务中心");
        mzPatient.setHsorgOpter("长沙市医疗保障事务中心");
        GetDropdownBox getDropdownBox = dao.userInfo(TokenUtil.getTokenUserId());
        // 医疗机构填报人
        mzPatient.setMedinsFillPsn(getDropdownBox.getName());
        // 医疗机构填报部门
        mzPatient.setMedinsFillDept(getDropdownBox.getDeptName());
        // 票据号码
        mzPatient.setBillNo(dao.mzBillNo(patNo, times));
        mzPatient.setBillCode("143001913350");
        // 判断  结算清单中职工参保人的单位及地址不能为空,如果是空的那么就
        if (StringUtil.isBlank(mzPatient.getEmpName())) {
            mzPatient.setEmpName("居家");
        }
        if (StringUtil.isBlank(mzPatient.getEmpAddr())) {
            mzPatient.setEmpAddr(mzPatient.getCurrAddr());
        }
        if (StringUtil.isBlank(mzPatient.getEmpTel())) {
            mzPatient.setEmpTel(mzPatient.getConerTel());
        }

        String setlId = upldCollection.getSetlinfo().getSetlId();
        ResultVo<List<MzChargitems>> listResultVo = getmZChrgitems(patNo, setlId, mzPatient.getMdtrtId(), upldCollection.getSetlinfo().getInsuplc());
        if (listResultVo.getCode() != 200) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, listResultVo.getMessage());
        }
        // 收费信息
        upldCollection.setIteminfo(EntityCopy.CopyList(listResultVo.getData(), IteminfoUpld.class));
        //基金支付类型
        upldCollection.setPayinfo(dao.payinfoUpld(patNo, times, ledgerSn));
        IteminfoUpld heJi = new IteminfoUpld();
        if (ListUtil.notBlank(upldCollection.getIteminfo())) {
            for (IteminfoUpld item : upldCollection.getIteminfo()) {
                heJi.setMedChrgitm(TOTAL_AMOUNT_CODE);
                heJi.setAmt(DecimalUtil.add(heJi.getAmt(), item.getAmt()));
                heJi.setClaaSumfee(DecimalUtil.add(heJi.getClaaSumfee(), item.getClaaSumfee()));
                heJi.setClabAmt(DecimalUtil.add(heJi.getClabAmt(), item.getClabAmt()));
                heJi.setFulamtOwnpayAmt(DecimalUtil.add(heJi.getFulamtOwnpayAmt(), item.getFulamtOwnpayAmt()));
                heJi.setOthAmt(DecimalUtil.add(heJi.getOthAmt(), item.getOthAmt()));
            }
            upldCollection.getIteminfo().add(heJi);
        }
        if (ListUtil.notBlank(upldCollection.getPayinfo())) {
            for (PayinfoUpld item : upldCollection.getPayinfo()) {
                upldCollection.getSetlinfo().setPsnSelfpay(DecimalUtil.minus(heJi.getAmt(), item.getFundPayamt()));
                upldCollection.getSetlinfo().setPsnCashpay(upldCollection.getSetlinfo().getPsnSelfpay());
            }
        }
        return ResultVoUtil.success(upldCollection);
    }


    /**
     * 修改患者的医疗类别
     *
     * @param iptMenType 修改的类型
     * @param setlId     setid
     * @return 提示
     */
    public ResultVo<String> modifyMedicalCategory(String iptMenType, String setlId) {
        dao.modifyMedicalCategory(iptMenType, setlId);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, "修改成功。");
    }

    /**
     * 添加或修改输血量
     * id 为 -1 代表新增数据
     *
     * @return 提示
     */
    public ResultVo<String> addOrModifyBloodTransfusionVolume(PatientBldInfo param) {
        if (param.getId() == -1) {
            dao.addBloodTransfusionInformation(param);
        } else {
            dao.updateBloodTransfusionVarieties(param);
        }
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION);
    }

    public ResultVo<String> removeBloodTransfusion(Integer id) {
        dao.removeBloodTransfusion(id);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION);
    }

    public void exportAutoUploadInfo(HttpServletResponse response, String startTime, String endTime) {
        List<TAutoUploadBill> list = dao.exportAutoUploadInfo(startTime, endTime);
        if (ListUtil.isBlank(list)) {
            throw new BizException(ExceptionEnum.INTERNAL_SERVER_ERROR, "没有查到数据");
        }
        String[] title = {"住院号", "住院次数", "上传时间", "日志", "患者结算时间"};
        String[][] content = new String[list.size()][];
        for (int i = 0, len = list.size(); i < len; i++) {
            content[i] = new String[title.length];
            TAutoUploadBill pojo = list.get(i);
            content[i][0] = pojo.getPatNo();
            content[i][1] = pojo.getTimes().toString();
            content[i][2] = DateUtil.formatDatetime(pojo.getCreatedDate());
            content[i][3] = pojo.getLogText();
            content[i][4] = DateUtil.formatDatetime(pojo.getUploadDate(), DateUtil.DATE);
        }
        ExcelUtil.exportExcel(response, title, content);
    }

}
