package thyyxxk.webserver.service.medicalinsurance;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
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.RequiredArgsConstructor;
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.FundPayType;
import thyyxxk.webserver.constants.sidicts.Insutype;
import thyyxxk.webserver.constants.sidicts.MdcsType;
import thyyxxk.webserver.constants.sidicts.MedChrgitmType;
import thyyxxk.webserver.constants.sidicts.MedType;
import thyyxxk.webserver.constants.sidicts.PsnIdetType;
import thyyxxk.webserver.constants.sidicts.PsnType;
import thyyxxk.webserver.constants.sidicts.SiFunction;
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.HeadInfo;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.casefrontsheet.CaseFrontsheetMain;
import thyyxxk.webserver.entity.casefrontsheet.request.SheetOverview;
import thyyxxk.webserver.entity.datamodify.GetDropdownBox;
import thyyxxk.webserver.entity.datamodify.TYbSetModifyTime;
import thyyxxk.webserver.entity.datamodify.TYbSetlModifyReq;
import thyyxxk.webserver.entity.dictionary.CodeName;
import thyyxxk.webserver.entity.drg.BaseInfo;
import thyyxxk.webserver.entity.drg.DiseInfoList;
import thyyxxk.webserver.entity.drg.OprtInfoList;
import thyyxxk.webserver.entity.inpatient.ZyActpatient;
import thyyxxk.webserver.entity.inpatient.charge.PatientParam;
import thyyxxk.webserver.entity.login.UserInfo;
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.DiseinfoUpldTemp;
import thyyxxk.webserver.entity.medicalinsurance.setllistupldTemp.IcuinfoUpldTemp;
import thyyxxk.webserver.entity.medicalinsurance.setllistupldTemp.IteminfoUpldTemp;
import thyyxxk.webserver.entity.medicalinsurance.setllistupldTemp.OprninfoUpldTemp;
import thyyxxk.webserver.entity.medicalinsurance.setllistupldTemp.OpspdiseinfoUpldTemp;
import thyyxxk.webserver.entity.medicalinsurance.setllistupldTemp.PayinfoUpldTemp;
import thyyxxk.webserver.entity.medicalinsurance.setllistupldTemp.SetlinfoUpldTemp;
import thyyxxk.webserver.entity.medicalinsurance.setllistupldTemp.UpldCollectionTemp;
import thyyxxk.webserver.entity.querydata.AutoUploadBill;
import thyyxxk.webserver.entity.querydata.JieSuanDanChaXun;
import thyyxxk.webserver.entity.querydata.SiSetlinfoTemp;
import thyyxxk.webserver.entity.querydata.TSetlDeptConf;
import thyyxxk.webserver.entity.querydata.TUploadDrgGroup;
import thyyxxk.webserver.entity.vo.DrgGroupTestVO;
import thyyxxk.webserver.entity.vo.quality.DiseInfoListVO;
import thyyxxk.webserver.entity.vo.quality.GroupInfoVO;
import thyyxxk.webserver.entity.vo.quality.OprtInfoListVO;
import thyyxxk.webserver.entity.vo.quality.QualityInfoVO;
import thyyxxk.webserver.entity.vo.quality.SetlBaseInfoVO;
import thyyxxk.webserver.http.drg.DrgWebApi;
import thyyxxk.webserver.http.websocket.SocketV2;
import thyyxxk.webserver.http.websocket.dto.WebSocketByUserCode;
import thyyxxk.webserver.service.PublicServer;
import thyyxxk.webserver.service.hutoolcache.DeptCache;
import thyyxxk.webserver.service.hutoolcache.NationCache;
import thyyxxk.webserver.service.hutoolcache.RegionCache;
import thyyxxk.webserver.service.hutoolcache.RelativeCache;
import thyyxxk.webserver.service.hutoolcache.UserCache;
import thyyxxk.webserver.service.inpatient.casefrontsheet.CaseFrontSheetMainService;
import thyyxxk.webserver.service.inpatient.casefrontsheet.VerifyCaseFrontSheet;
import thyyxxk.webserver.service.inpatient.charge.CashierProcessService;
import thyyxxk.webserver.service.outpatient.wxapi.SendWxInfoService;
import thyyxxk.webserver.utils.*;

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
@RequiredArgsConstructor
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 AutoUploadBillService autoUploadBillService;
    private final TSetlDeptConfService tSetlDeptConfService;
    private final TUploadDrgGroupService tUploadDrgGroupService;
    private final SiLogService siLogService;
    private final SocketV2 intergrationPlatformSocket;
    private final UserCache userCache;
    private final DeptCache deptCache;
    private final NationCache nationCache;
    private final RegionCache regionCache;
    private final RelativeCache relativeCache;
    private final DrgWebApi drgWebApi;
    private final CashierProcessService cashierProcessService;

    /**
     * 上传到医保的结算单上传
     *
     * @param patNo     住院号
     * @param times     住院次数
     * @param ledgerSn  账页号
     * @param checkFlag 是否需要检验参数
     * @return 返回体术
     * @throws Exception 错误
     */
    public ResultVo<String> upldSetlList(String patNo, Integer times, Integer ledgerSn, boolean checkFlag) throws Exception {
        ResultVo<UpldCollection> upldCollection = getUploadInfo(patNo, times, ledgerSn);
        if (ledgerSn != 0) {
            dealDrgGroup(patNo, times, ledgerSn, upldCollection.getData().getSetlinfo());
        }
        if (checkFlag) {
            checkUploadCondition(patNo, upldCollection, times);
        }
        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);
        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());
            try {
                settlementDocDataReceipt(upldCollection.getData());
            } catch (Exception e) {
                e.printStackTrace();
            }
            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));
    }

    /**
     * @description: 给责任护士医保码 和名称  补偿机制
     * @author: lihong
     * @date: 2023/3/22 15:22
     * @param: patNo
     * @param: times
     * @return: java.lang.String[]
     **/
    private void setRespNurs(SetlinfoUpld setlinfoUpld, String patNo, Integer times) {
        List<String> respNursCodeList = dao.getRespNursCode(patNo, times);
        if (CollUtil.isNotEmpty(respNursCodeList)) {
            for (int i = 0; i < respNursCodeList.size(); i++) {
                String ybCode = getYbCode(respNursCodeList.get(i));
                if (i == (respNursCodeList.size() - 1) && StringUtil.notBlank(ybCode)) {
                    setlinfoUpld.setRespNursCode(ybCode);
                    setlinfoUpld.setRespNursName(userCache.getEmployeeName(respNursCodeList.get(i)));
                    return;
                }
                if (StringUtil.notBlank(ybCode) && ybCode.startsWith("N")) {
                    setlinfoUpld.setRespNursCode(ybCode);
                    setlinfoUpld.setRespNursName(userCache.getEmployeeName(respNursCodeList.get(i)));
                    return;
                }
            }
        }
    }


    public void dealDrgGroup(String patNo, Integer times, Integer ledgerSn, SetlinfoUpld setlinfo) {
        SiLog siLog = new SiLog(exec.makeMsgId(), SiFunction.DRG_GROUP_INFO.getCode(), setlinfo.getInsuplc(),
                TokenUtil.getInstance().getTokenUserId(), null, null, patNo, times, ledgerSn, 1, setlinfo.getPsnNo());
        try {
            int flag = getModifyFlag(patNo, times);
            List<YbZyDisDiag> ybZyDisDiags = dao.zhenDuanXinXi(patNo, times, flag == 1 ? "zy_dis_diag_yb_modify" : "zy_dis_diag_yb");
            List<BatjBa4> batjBa4s = dao.shouShuXinXi(patNo, times, flag == 1 ? "batj_ba4_modify" : "batj_ba4");
            ZyInactpatient param = new ZyInactpatient();
            param.setInpatientNo(patNo);
            param.setAdmissTimes(times);
            param.setNewYbZyDisDiag(ybZyDisDiags);
            param.setNewBatjBa4(batjBa4s);
            param.setMedfeeSumamt(dao.getsetlTotalFee(patNo, times, ledgerSn));
            Map<String, Object> temp = getDrgQualityResult(param, setlinfo);
            JSONObject resultInfo = (JSONObject) temp.get("result");
            Object drgParam = temp.get("param");
            siLog.setBody(JSON.toJSONString(drgParam));
            siLog.setResult(JSON.toJSONString(resultInfo));
            if (resultInfo.getBooleanValue("isSuccess")) {
                JSONObject groupInfo = resultInfo.getJSONObject("result").getJSONObject("group_info");
                GroupInfoVO groupInfoVO = JSON.parseObject(JSON.toJSONString(groupInfo), GroupInfoVO.class);
                log.info("分组结果[groupInfoVO]:{}", JSON.toJSONString(groupInfoVO));
                siLog.setInfcode(0);
                if (groupInfoVO != null) {
                    Map<String, Object> groupInfoVOMap = BeanUtil.beanToMap(groupInfoVO, false, true);
                    TUploadDrgGroup uploadDrgGroup = new TUploadDrgGroup();
                    CopyOptions options = new CopyOptions();
                    options.setIgnoreProperties("group_messages");
                    BeanUtil.fillBeanWithMap(groupInfoVOMap, uploadDrgGroup, true, options);
                    uploadDrgGroup.setPatNo(patNo);
                    uploadDrgGroup.setTimes(times);
                    uploadDrgGroup.setLedgerSn(ledgerSn);
                    uploadDrgGroup.setSetlTime(setlinfo.getSetlEndDate());
                    uploadDrgGroup.setTotalFee(param.getMedfeeSumamt());
                    if (ListUtil.notBlank(groupInfoVO.getGroup_messages())) {
                        uploadDrgGroup.setGroupMessages(CollUtil.join(groupInfoVO.getGroup_messages(), ";"));
                    }
                    tUploadDrgGroupService.delAndSaveData(uploadDrgGroup);
                }
            }
        } catch (Exception e) {
            siLog.setInfcode(-1);
            siLog.setBody("{\"errMsg\":\"处理分组结果报错\"}");
            log.error("处理分组结果报错", e);
        }
        siLogService.delAndSave(siLog);
    }

    private void checkUploadCondition(String patNo, ResultVo<UpldCollection> upldCollection, Integer times) {
        if (upldCollection.getCode() != 200) {
            throw new BizException(ExceptionEnum.INTERNAL_SERVER_ERROR, upldCollection.getMessage());
        }
        StringBuilder errorMessage = new StringBuilder();

        if (!patNo.startsWith("JT") && patNo.indexOf("-") == 0) {
            if (StringUtil.isBlank(upldCollection.getData().getSetlinfo().getConerName())) {
                errorMessage.append("患者联系人姓名不能为空。");
            }
        }
        SetlinfoUpld temp = upldCollection.getData().getSetlinfo();
        if (StringUtil.isBlank(temp.getChfpdrCode())) {
            errorMessage.append("主诊医师编码为空。");
        }
        if (!patNo.contains("-")) {
            if (StringUtil.isBlank(temp.getRespNursCode())) {
                errorMessage.append("责任护士编码为空。");
            }
        }

        if (ListUtil.notBlank(upldCollection.getData().getOprninfo())) {
            for (OprninfoUpld item : upldCollection.getData().getOprninfo()) {
                if (StringUtil.isBlank(item.getOperDrCode())) {
                    errorMessage.append(String.format("医生：【%s】，没有医保编码请去职工字典数据维护中添加", null == item.getOperDrName() ? "没有填写医生" : item.getOperDrName()));
                }
                if (StringUtil.notBlank(item.getAnstDrName()) && StringUtil.isBlank(item.getAnstDrCode())) {
                    errorMessage.append(String.format("医生：【%s】，没有医保编码请去职工字典数据维护中添加", null == item.getAnstDrName() ? "没有填写医生" : item.getAnstDrName()));
                }
                if (StringUtil.notBlank(item.getAnstDrName()) && (StringUtil.isBlank(item.getAnstBegntime()) || StringUtil.isBlank(item.getAnstEndtime()))) {
                    errorMessage.append(String.format("手术：【%s】，有麻醉医生，没有麻时间请填写", item.getOprnOprtName()));
                }
                if (StringUtil.isBlank(item.getOprnOprtEndtime())) {
                    errorMessage.append(String.format("手术：【%s】，手术结束时间为空。", item.getOprnOprtName()));
                }
            }
        }

        String tempError = errorMessage.toString();
        if (StringUtil.notBlank(tempError)) {
            throw new BizException(ExceptionEnum.INTERNAL_SERVER_ERROR, tempError);
        }
    }


    public void settlementDocDataReceipt(UpldCollection param) {
        SetlinfoUpld setlinfo = param.getSetlinfo();
        String setlId = setlinfo.getSetlId();
        Integer id = dao.whetherThereIsUploadInfo(setlinfo.getSetlId());
        if (id != null) {
            dao.deleteAccordingToSetlId(setlinfo.getSetlId());
        }
        // 结算清单信息
        dao.insert(setlinfo);
        // 基金支付信息
        List<PayinfoUpld> payinfo = param.getPayinfo();
        if (ListUtil.notBlank(payinfo)) {
            dao.insertFundPaymentInfoOfStatement(setlId, payinfo);
        }
        //插入收费项目信息
        List<IteminfoUpld> iteminfo = param.getIteminfo();
        if (ListUtil.notBlank(iteminfo)) {
            dao.insertChargingItemInfo(setlId, iteminfo);
        }
        // 插入门诊慢特病信息
        List<OpspdiseinfoUpld> opspdiseinfo = param.getOpspdiseinfo();
        if (ListUtil.notBlank(opspdiseinfo)) {
            dao.insertionOfOutpatientChronicDiseases(setlId, opspdiseinfo);
        }
        // 获取患者诊断
        List<DiseinfoUpld> diseinfo = param.getDiseinfo();
        if (ListUtil.notBlank(diseinfo)) {
            dao.insertStatementDiagnosisInfo(setlId, diseinfo);
        }
        // 手术操作信息
        List<OprninfoUpld> oprninfo = param.getOprninfo();
        if (ListUtil.notBlank(oprninfo)) {
            dao.insertSurgicalOperationInfo(setlId, oprninfo);
        }
        // 重症监护信息
        List<IcuinfoUpld> icuinfo = param.getIcuinfo();
        if (ListUtil.notBlank(icuinfo)) {
            dao.insertIntensiveCareInfor(setlId, icuinfo);
        }
        // 输血信息
        List<Bldinfo> bldinfo = param.getBldinfo();
        if (ListUtil.notBlank(bldinfo)) {
            dao.insertTransfusionInfo(setlId, bldinfo);
        }
    }


    /**
     * 获取上传到医保的信息
     *
     * @param patNo    住院号
     * @param times    住院次数
     * @param ledgerSn 账页号
     * @return 返回上传的结算单信息
     * @throws Exception 错误
     */
    public ResultVo<UpldCollection> getUploadInfo(String patNo, Integer times, Integer ledgerSn) throws Exception {
        if (ledgerSn == 0) {
            return outpatInformation(patNo, times, ledgerSn);
        }

        SetlinfoUpld setlinfoUpld = getSetlinfoUpldInfo(patNo, times, ledgerSn);
        if (StringUtil.isBlank(setlinfoUpld.getSetlId())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "结算id为空");
        }
        int flag = getModifyFlag(patNo, times);
        // 手术
        List<OprninfoUpld> oprninfoUpld = dao.oprninfoUplds(patNo, times, flag == 1 ? "batj_ba4_modify" : "batj_ba4");

        if (ListUtil.notBlank(oprninfoUpld)) {
            // 手术计数
            setlinfoUpld.setOprnOprtCodeCnt(String.valueOf(oprninfoUpld.size()));
            for (int i = 0; i < oprninfoUpld.size(); i++) {
                // 手术操作类别
                oprninfoUpld.get(i).setOprnOprtType(i == 0 ? "1" : "2");
            }

        }

        // 诊断
        List<DiseinfoUpld> diseinfos = dao.diseinfo(patNo, times, flag == 1 ? "zy_dis_diag_yb_modify" : "zy_dis_diag_yb");
        if (ListUtil.notBlank(diseinfos)) {
            setlinfoUpld.setDiagCodeCnt(String.valueOf(diseinfos.size()));

            for (int i = 0; i < diseinfos.size(); i++) {
                diseinfos.get(i).setMaindiagFlag(i == 0 ? "1" : "0");
            }
        }

        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());
            }
        }

        // 甲类费用
        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(patNo, times, ledgerSn)) {
                    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);


        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);
        });

        return ResultVoUtil.success(upldCollection);
    }

    public boolean isFertilitySign(String patNo, Integer times, Integer ledgerSn) {
        boolean isFertilitySign = false;
        String medType = dao.getMedicalCategory(patNo, times, ledgerSn);
        if (StringUtil.notBlank(medType)) {
            String[] giveBirth = new String[]{"2106", "2017", "52", "51"};
            if (Arrays.asList(giveBirth).contains(medType)) {
                isFertilitySign = true;
            }
        }
        return isFertilitySign;
    }

    public void dealSetlinfoUpld(String patNo, Integer times, SetlinfoUpld setlinfoUpld) {
        // 患者基本信息 先判断签收表是否有数据
        //Integer existCaseFrontsheetMain = dao.existCaseFrontsheetMain(patNo, times);
        //if(existCaseFrontsheetMain ==null){
        //    这里使用病案首页数据
        covertCaseFrontsheetMain2SetlinfoUpld(setlinfoUpld, patNo, times);
        //}
    }


    /**
     * @description:病案首页转换为结算的的数据 用于签收表没有数据, 重新取数据
     * @author: lihong
     * @date: 2023/2/9 16:30
     * @param: setlinfoUpld
     * @param: patNo
     * @param: times
     **/
    public void covertCaseFrontsheetMain2SetlinfoUpld(SetlinfoUpld setlinfoUpld, String patNo, Integer times) {
        SheetOverview overview = new SheetOverview();
        overview.setInOutFlag(2);
        overview.setBah(patNo);
        overview.setTimes(times);
        CaseFrontsheetMain patientInfo = caseFrontSheetMainService.getPatientInfo(overview);
        if (patientInfo != null) {
            setlinfoUpld.setNtly(patientInfo.getCountry() != null ? dao.getCountrySiCode(patientInfo.getCountry()) : null);
            setlinfoUpld.setPrfs(StringUtil.isBlank(patientInfo.getOccupation()) ? getPrfs(setlinfoUpld) : patientInfo.getOccupation());
            setlinfoUpld.setCertno(patientInfo.getSocialNo());
            setlinfoUpld.setCurrAddr(patientInfo.getLivePlace());
            setlinfoUpld.setEmpName(patientInfo.getUnitName());
            setlinfoUpld.setEmpAddr(patientInfo.getUnitPlace());
            setlinfoUpld.setEmpTel(patientInfo.getUnitPhone());
            setlinfoUpld.setPoscode("310".equals(patientInfo.getInsutype()) && StringUtil.isBlank(patientInfo.getUnitZipCode()) ? "410000" : patientInfo.getUnitZipCode());
            setlinfoUpld.setNaty(nationCache.get(patientInfo.getNation()).getWjwCode());
            setlinfoUpld.setConerName(patientInfo.getContactName());
            setlinfoUpld.setBrdy(DateUtil.formatDatetime(patientInfo.getBirthDate(), "yyyy-MM-dd"));
            setlinfoUpld.setAge(String.valueOf(patientInfo.getAge()));
            setlinfoUpld.setGend(patientInfo.getSex());
            setlinfoUpld.setPatnRlts(relativeCache.get(patientInfo.getContactRelation()).getYbCode());
            setlinfoUpld.setConerTel(patientInfo.getContactPhone());
            setlinfoUpld.setPwcryBfadmComaDura(patientInfo.getComaDaysBeforeAdmiss() + "/" + patientInfo.getComaHoursBeforeAdmiss() + "/" + patientInfo.getComaMinutesBeforeAdmiss());
            setlinfoUpld.setPwcryAfadmComaDura(patientInfo.getComaDaysAfterAdmiss() + "/" + patientInfo.getComaHoursAfterAdmiss() + "/" + patientInfo.getComaMinutesAfterAdmiss());
            setlinfoUpld.setDscgWay(patientInfo.getZyDismissWay());
            setlinfoUpld.setAcpMedinsName(patientInfo.getDismissDestination());
            setlinfoUpld.setDaysRinpFlag31(patientInfo.getAdmissAgainInOneMonth());
            setlinfoUpld.setDaysRinpPup31(patientInfo.getAdmissAgainPurpose());
            setlinfoUpld.setChfpdrName(StringUtil.isBlank(patientInfo.getMainDoctorName()) ? patientInfo.getAdmissDoctorName() : patientInfo.getMainDoctorName());
            setlinfoUpld.setChfpdrCode(StringUtil.isBlank(getYbCode(patientInfo.getMainDoctor())) ? getYbCode(patientInfo.getAdmissDoctor()) : getYbCode(patientInfo.getMainDoctor()));
            setlinfoUpld.setNwbAge(patientInfo.getAgeDays() == null ? "" : patientInfo.getAgeDays().toString());
            setlinfoUpld.setConerAddr(StringUtil.isBlank(patientInfo.getContactAddrName()) ? patientInfo.getLivePlace() : patientInfo.getContactAddrName());
            setlinfoUpld.setNwbBirWt(patientInfo.getNewBornWeight() == null ? "" : patientInfo.getNewBornWeight().toString());
            setlinfoUpld.setAdmWay(StringUtil.isBlank(setlinfoUpld.getAdmWay()) ? StringUtil.isBlank(patientInfo.getZyAdmissWay()) ? "2" : patientInfo.getZyAdmissWay() : setlinfoUpld.getAdmWay());
            setlinfoUpld.setNwbAdmWt(Convert.toStr(patientInfo.getNewBornAdmissWeight(), ""));
            String dutyNurse = getYbCode(patientInfo.getDutyNurse());
            if (StringUtil.notBlank(dutyNurse)) {
                setlinfoUpld.setRespNursCode(dutyNurse);
            }
            if (StringUtil.notBlank(patientInfo.getDutyNurseName())) {
                setlinfoUpld.setRespNursName(patientInfo.getDutyNurseName());
            }
            String refldeptDept = deptCache.getYbDept(patientInfo.getTransDeptCode());
            if (refldeptDept != null) {
                setlinfoUpld.setRefldeptDept(refldeptDept);
            }
            String dscCaty = deptCache.getYbDept(patientInfo.getAdmissDeptCode());
            if (dscCaty != null) {
                setlinfoUpld.setDscgCaty(dscCaty);
            }
        }

    }

    //获取职业
    private String getPrfs(SetlinfoUpld setlinfoUpld) {
        if ("310".equals(setlinfoUpld.getHiType())) {
            return "17";
        } else {
            return "90";
        }
    }

    public String getYbCode(String code) {
        UserInfo userInfo = userCache.get(code);
        String ybCode = "";
        if (userInfo != null) {
            ybCode = userInfo.getYbCode();
        }
        return ybCode;
    }

    public int getModifyFlag(String patNo, Integer times) {
        TYbSetlModifyReq setlModifyReq = dao.getSetlModifyReq(patNo, times);
        Integer flag = setlModifyReq != null ? setlModifyReq.getAuditFlag() : null;
        String reRemark = setlModifyReq != null ? setlModifyReq.getReqRemark() : null;
        //有审核记录的就同步下数据
        if (flag != null && flag != 1) {
            //    这里判断 诊断和手术 修改表是否有数据  没有的话 就同步原表的数据
            Integer existDiseDiag = dao.existDiseDiag(patNo, times);
            if (existDiseDiag == null) {
                dao.synchronousDisDiag(patNo, times);
            }
            Integer exisOprt = dao.exisOprt(patNo, times);
            if (exisOprt == null && StringUtil.notBlank(reRemark) && !reRemark.contains("手术有变动")) {
                dao.synchronousOprt(patNo, times);
            }
        }
        flag = flag == null ? 0 : 1;
        return flag;
    }


    private String getDrgHaiPay(String insuplcAdmdvs, String defaultValue, Date setlTime) {
        if (setlTime.getTime() < DateUtil.parse("2023-01-01", "yyyy-MM-dd").getTime()) {
            return "3";
        }
        if (StringUtil.isBlank(insuplcAdmdvs)) {
            return defaultValue;
        }
        if ("4".equals(defaultValue)) {
            return defaultValue;
        }
        // 长沙 4301 株洲4302   湘潭 4303   衡阳4304  郴州4310 省本级 439900
        if ("439900".equals(insuplcAdmdvs)) {
            return "4";
        }
        String[] drgCityCode = {"4301", "4302", "4303", "4304", "4310"};
        for (String code : drgCityCode) {
            if (insuplcAdmdvs.startsWith(code)) {
                return "4";
            }
        }
        return defaultValue;
    }


    /**
     * 特级护理天数如果是 0 就不传值
     *
     * @param days
     * @return
     */
    private String nursingDays(Integer days) {
        if (days == null) {
            return null;
        } else if (days.equals(0)) {
            return null;
        } else {
            return String.valueOf(days);
        }
    }

    @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;
                    if (chuYuanShiJian == null) {
                        continue;
                    }
                    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 {
        int flag = getModifyFlag(patNo, times);
        // 查询出来的信息
        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().setInsuplcAdmdvsName(regionCache.get(temp.getSetlinfo().getInsuplc()));
        //入院科别
        temp.getSetlinfo().setAdmCatyName(deptCache.getYbDeptName(temp.getSetlinfo().getAdmCaty()));
        // 转科科别
        temp.getSetlinfo().setRefldeptDeptName(deptCache.getYbDeptName(temp.getSetlinfo().getRefldeptDept()));
        // 出院科别
        temp.getSetlinfo().setDscgCatyName(deptCache.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, "请选择需要上传的患者。");
        }
        boolean checkFlag = isCheckFlag();
        boolean checkAuditFlag = isCheckAuditFlag();
        if (checkAuditFlag && isDrghiPaymtd(param.stream().map(obj -> obj.getHiPaymtd()).collect(Collectors.toList()))) {
            List<String> visitIds = param.stream().map(obj -> obj.getPatNo() + obj.getTimes()).collect(Collectors.toList());
            List<Integer> auditFlags = dao.listSetlModifyReq(visitIds);
            if (ListUtil.notBlank(auditFlags)) {
                boolean flag = auditFlags.stream().allMatch(obj -> obj == 1);
                if (!flag || auditFlags.size() < param.size()) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "选中上传的患者审核状态必须要全部为审核通过。");
                }
            } else {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "选中上传的患者审核状态必须要全部为审核通过。");
            }
        }
        List<AutoUploadBill> autoUploadBills = new ArrayList<>();
        for (int i = 0; i < param.size(); i++) {
            SiSetlinfoTemp siPatInfo = param.get(i);
            AutoUploadBill autoUploadBill = getAutoUploadBillAndUpload(siPatInfo.getPatNo(), siPatInfo.getTimes(), siPatInfo.getLedgerSn(), siPatInfo.getSetlTime(), checkFlag, true, i + 1, param.size(), siPatInfo);
            autoUploadBills.add(autoUploadBill);
        }
        autoUploadBillService.asyncSaveData(autoUploadBills);
        return ResultVoUtil.success();
    }

    /**
     * @description:重新上传
     * @author: lihong
     * @date: 2023/2/2 10:04
     * @param: patNo
     * @param: times
     * @param: ledgerSn
     * @param: setlTime
     **/
    public void reUpload(String patNo, Integer times, Integer ledgerSn, Date setTime, String setlListId) {
        if (StringUtil.isBlank(setlListId)) {
            return;
        }
        List<AutoUploadBill> autoUploadBills = new ArrayList<>();
        AutoUploadBill autoUploadBill = getAutoUploadBillAndUpload(patNo, times, ledgerSn, setTime, false, false, 0, 0, null);
        autoUploadBills.add(autoUploadBill);
        autoUploadBillService.asyncSaveData(autoUploadBills);
        if (autoUploadBill.getFlag() == AutoUploadBill.FLAG.UPLOAD_FAIL.getCode()) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "对已经上传的数据进行重新上传,[上传失败],详情:" + StringUtil.substring(autoUploadBill.getLogText(), 0, 200));
        }
    }

    /**
     * @description:获取日志并且上传
     * @author: lihong
     * @date: 2023/2/2 16:36
     * @param: patNo
     * @param: times
     * @param: ledgerSn
     * @param: setTime
     * @param: sendMessageFlag 是否发送消息
     * @param: index
     * @param: size
     * @param: siPatInfo
     * @return: thyyxxk.webserver.entity.querydata.AutoUploadBill
     **/
    public AutoUploadBill getAutoUploadBillAndUpload(String patNo, Integer times, Integer ledgerSn, Date setTime, boolean checkFlag, boolean sendMessageFlag, int index, int size, SiSetlinfoTemp siPatInfo) {
        AutoUploadBill autoUploadBill = new AutoUploadBill();
        try {
            String userId = TokenUtil.getInstance().getTokenUserId();
            String userName = publicServer.huoQuYuanGongXinXi(userId).getName();
            autoUploadBill.setPatNo(patNo);
            autoUploadBill.setTimes(times);
            autoUploadBill.setLedgerSn(ledgerSn);
            autoUploadBill.setTypeFlag(AutoUploadBill.TypeFlag.SD_UPLOAD.getCode());
            autoUploadBill.setUploadDate(new Date());
            autoUploadBill.setSetlTime(setTime);
            autoUploadBill.setCreatedDate(new Date());
            autoUploadBill.setUploadCode(userId);
            autoUploadBill.setUploadName(userName);
            ResultVo<String> resultVo = upldSetlList(patNo, times, ledgerSn, checkFlag);
            autoUploadBill.setLogText(resultVo.getMessage());
            autoUploadBill.setFlag(resultVo.getCode() == 200 ? AutoUploadBill.FLAG.UPLOAD_SUCCESS.getCode() : AutoUploadBill.FLAG.UPLOAD_FAIL.getCode());
            if (sendMessageFlag) {
                upldSetlErrorMessage(patNo, times, ledgerSn, resultVo.getMessage(), resultVo.getCode() == 200 ? 0 : 1, index, size, siPatInfo.getOutDeptName(), siPatInfo.getPsnName(), siPatInfo.getReferPhysicianName());
            }
        } catch (Exception e) {
            log.error("结算单重新上传错误", e);
            autoUploadBill.setLogText(e.getCause().getMessage());
            autoUploadBill.setFlag(AutoUploadBill.FLAG.UPLOAD_FAIL.getCode());
            if (sendMessageFlag) {
                upldSetlErrorMessage(siPatInfo.getPatNo(), siPatInfo.getTimes(), siPatInfo.getLedgerSn(), e.getCause().getMessage(), 2, index, size, siPatInfo.getOutDeptName(), siPatInfo.getPsnName(), siPatInfo.getReferPhysicianName());
            }
        }
        return autoUploadBill;
    }

    public boolean isCheckFlag() {
        String checkUploadFlag = dao.getDictValueByDictName("1.3", "check_upload_flag");
        return "1".equals(checkUploadFlag);
    }

    public boolean isCheckAuditFlag() {
        String checkUploadFlag = dao.getDictValueByDictName("1.4", "check_audit_flag");
        return "1".equals(checkUploadFlag);
    }

    /**
     * 全部上传
     *
     * @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, "没有要上传的信息。");
            }
            boolean checkAuditFlag = isCheckAuditFlag();
            //只有drg的需要审核,其他不用
            if (checkAuditFlag && isDrghiPaymtd(list.stream().map(obj -> obj.getHiPaymtd()).collect(Collectors.toList()))) {
                // 只有全部为审核通过的数据才能上传
                boolean isAllAuditPass = list.stream().allMatch(obj -> obj.getAuditFlag() != null && obj.getAuditFlag() == 1);
                if (!isAllAuditPass) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "要所有数据为审核通过状态才能全部上传。");
                }
            }
            upldSetlListBatch(list);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("时间范围上传结算单错误：{}", JSON.toJSONString(e));
        }
        return ResultVoUtil.success();
    }

    /**
     * @description:是否有drg支付数据
     * @author: lihong
     * @date: 2023/1/28 15:52
     * @param: hiPaymtds
     * @return: boolean
     **/
    private boolean isDrghiPaymtd(List<Integer> hiPaymtds) {
        if (ListUtil.notBlank(hiPaymtds)) {
            return hiPaymtds.stream().anyMatch(obj -> obj != null && obj == 4);
        }
        return false;
    }

    /**
     * 发送医保上传的错误信息
     *
     * @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));
        String message = SocketMsg.socketVo(Message.JDT_MESSAGE, obj);

        WebSocketByUserCode messageBody = WebSocketByUserCode.create(TokenUtil.getInstance().getTokenUserId(), message);
        intergrationPlatformSocket.sendMessageByUserCode(messageBody);
        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);
        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<>();
        //获取截上传截止天数,结算时间后截止几天到期
        String dictValue = dao.getDictValueByDictName("1.1", "1");
        QueryWrapper<?> queryWrapper = statementQueryConditions(param, dictValue);
        page.setRecords(dao.huoQuJieSuanRenYuan(queryWrapper,
                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());
            }

            if (dao.countZy(item.getPatNo(), item.getTimes()) == null) {
                if (item.getLedgerSn() == 1) {
                    setDisDate(item);
                }
            } else {
                setDisDate(item);
            }
            item.setUploadUpdateReminder(getUploadUpdateReminder(item.getPatNo(), item.getTimes(), item.getLedgerSn(), item.getSetlListId()));
            item.setUploadStatus(StringUtil.isBlank(item.getSetlListId()) ? "未上传" : "已上传");
            //质控提醒
            boolean qualityPassFlag = isQualityPass(item.getPatNo(), item.getTimes());
            item.setQualityReminder(getQualityReminder(item.getSetlTime(), qualityPassFlag));
            item.setUploadCutoffDate(getUploadCutoffDate(dictValue, item.getSetlTime(), item.getSetlListId()));
            item.setInsuplcAdmdvsName(regionCache.get(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()));
                    }
                }
            }
        }
        page.setTotal(dao.huoQuJieSuanRenYuanTotal(queryWrapper));
        return ResultVoUtil.success(page);
    }

    public void setDisDate(SiSetlinfoTemp item) {
        Map<String, Date> setTimeMap = dao.selelctSetlBeginAndEndTime(item.getPatNo(), item.getTimes(), item.getLedgerSn());
        item.setDisDate(setTimeMap.get("endtime"));
        long between = cn.hutool.core.date.DateUtil.betweenDay(setTimeMap.get("begntime"), setTimeMap.get("endtime"), true);
        item.setActIptDays(Convert.toStr(between == 0 ? 1 : between));
    }

    private String getUploadUpdateReminder(String patNo, Integer times, Integer ledgerSn, String setlListId) {
        if (StringUtil.notBlank(setlListId)) {
            Date lastUpdateTimeime = autoUploadBillService.getLastUpdateTime(patNo, times, ledgerSn);
            if (lastUpdateTimeime != null) {
                Date now = new Date();
                int temp = (int) cn.hutool.core.date.DateUtil.betweenDay(lastUpdateTimeime, now, true);
                int diff = 5 - temp == 0 ? 1 : 5 - temp;
                if (diff < 0) {
                    return "已上传超过【5】天,医保不能重新上传数据";
                } else {
                    return "上传后还剩【" + diff + "】天,医保将不能重新上传数据,要修改请尽快";
                }
            }
        }
        return "";
    }

    private String getQualityReminder(Date setlTime, boolean qualityPassFlag) {
        Date now = new Date();
        int diffDay = DateUtil.daysBetween(now, setlTime);
        if (diffDay >= 3 && !qualityPassFlag) {
            return "超过【" + diffDay + "】天未质控通过,请尽快审核通过并上传";
        }
        return "";
    }

    /**
     * @description:获取上传截止时间
     * @author: lihong
     * @date: 2022/12/26 11:27
     * @param: dictValue
     * @param: setlTime
     **/
    private String getUploadCutoffDate(String dictValue, Date setlTime, String setlListId) {
        String result = "";
        Date now = new Date();
        int days = Integer.parseInt(dictValue);
        long diffDay = cn.hutool.core.date.DateUtil.betweenDay(setlTime, now, true);
        if (StringUtil.isBlank(setlListId)) {
            //未上传
            if (diffDay < days) {
                result = "距离上传截止时间还剩【" + (days - diffDay) + "】天";
            } else {
                result = "上传截止时间超期【" + (diffDay - days) + "】天";
            }
        }
        return result;
    }

    /**
     * 结算单上传条件查询
     *
     * @param param 参数
     * @return 返回
     */
    private QueryWrapper<?> statementQueryConditions(JieSuanDanChaXun param, String day) {
        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 (param.getTimes() != null) {
            qw.eq("a.times", param.getTimes());
        }
        if (StringUtil.notBlank(param.getName())) {
            qw.likeRight("a.psn_name", param.getName());
        }
        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());
        } else {
            //只查省内的
            qw.likeRight("insuplc_admdvs", "43");
        }
        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 (ListUtil.notBlank(param.getAuditFlag()) && !param.getAuditFlag().contains(All)) {
            List<Integer> auditFlags = param.getAuditFlag();
            if (auditFlags.stream().anyMatch(o -> o == 5)) {
                if (auditFlags.stream().allMatch(o -> o == 5)) {
                    qw.isNull("c.audit_flag");
                } else {
                    StringBuilder auditFlagSql = new StringBuilder();
                    List<Integer> neqFive = auditFlags.stream().filter(obj -> obj != 5).collect(Collectors.toList());
                    auditFlagSql.append(" (c.audit_flag is null or c.audit_flag in (" + CollUtil.join(neqFive, ",") + ") ) ");
                    qw.apply(auditFlagSql.toString());
                }
            } else {
                qw.in("c.audit_flag", auditFlags);
            }
        }

        if (param.getHiPaymtd() != null && param.getHiPaymtd() != 0) {
            qw.eq("a.hi_paymtd", param.getHiPaymtd());
        }
        if (StringUtil.notBlank(param.getReferPhysician())) {
            qw.eq("isnull(b.refer_physician,bb.zyys)", param.getReferPhysician());
        }
        if (param.getYbSf() != null) {
            qw.eq("a.hi_paymtd", 4);
            if (param.getYbSf() == 1) {
                //    省本级
                qw.eq("a.insuplc_admdvs", "439900");
            }
            //长沙市
            if (param.getYbSf() == 2) {
                qw.likeRight("a.insuplc_admdvs", "4301");
            }
            //省内异地
            if (param.getYbSf() == 3) {
                qw.apply(" a.insuplc_admdvs !='439900' and a.insuplc_admdvs not like '4301%' ");
            }
        }
        if (ListUtil.notBlank(param.getUploadJieZhiDay())) {
            Integer value = Integer.parseInt(day);
            StringBuilder result = new StringBuilder();
            for (int i = 0; i < param.getUploadJieZhiDay().size(); i++) {
                Integer temp = value - param.getUploadJieZhiDay().get(i);
                if (i >= param.getUploadJieZhiDay().size() - 1) {
                    result.append(temp);
                } else {
                    result.append(temp);
                    result.append(",");
                }
            }
            qw.inSql(" DATEDIFF(day,a.setl_time,GETDATE()) ", result.toString());
        }
        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) {
        List<SiSetlinfoTemp> list = new ArrayList<>();
        if (ListUtil.notBlank(param.getSiSetlinfoTemps())) {
            list.addAll(param.getSiSetlinfoTemps());
        } else {
            param.setPageSize(10000);
            param.setCurrentPage(1);
            list.addAll(huoQuJieSuanRenYuan(param).getData().getRecords());
        }
        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.getQualityReminder();
            content[i][3] = pojo.getUploadCutoffDate();
            content[i][4] = pojo.getUploadStatus();
            content[i][5] = pojo.getDecTypeName();
            content[i][6] = pojo.getOutDeptName();
            content[i][7] = pojo.getPatNo();
            content[i][8] = pojo.getGendName();
            content[i][9] = pojo.getActIptDays();
            content[i][10] = pojo.getDisDiag();
            content[i][11] = pojo.getDisDiagComment();
            content[i][12] = pojo.getOperationName();
            content[i][13] = pojo.getMedfeeSumamt();
            content[i][14] = pojo.getFundPaySumamt();
            content[i][15] = pojo.getInsutypeName();
            content[i][16] = pojo.getPsnTypeName();
            content[i][17] = DateUtil.formatDatetime(pojo.getSetlTime(), GetDateFormat.DATE_TIME);
            content[i][18] = pojo.getMedTypeName();
            content[i][19] = pojo.getClrOptinsName();
            content[i][20] = pojo.getInsuplcAdmdvsName();
            content[i][21] = pojo.getReferPhysicianName();
            content[i][22] = pojo.getZhuanKeName() == null ? "" : pojo.getZhuanKeName().toString();
            content[i][23] = pojo.getZhuanKeAmount() == null ? "" : pojo.getZhuanKeAmount().toString();
            content[i][24] = pojo.getReqRemark();
            content[i][25] = pojo.getBmyBz();
            content[i][26] = DateUtil.formatDatetime(pojo.getDisDate(), GetDateFormat.DATE_TIME);
        }
        //传三个参数 一个是 固定的 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, "zy_inactpatient");
        if (zy == null) {
            zy = dao.huanZheXinXi(patNo, times, "zy_actpatient");
        }
        // 在这里带出 患者病案首页的 入院病情
        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(getPatienYbZyDisDiag(patNo, times));
        zy.setNewYbZyDisDiag(dao.zhenDuanXinXi(patNo, times, "zy_dis_diag_yb_modify"));

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

        setDrgInfo(zy, setlinfoUpld.getAdmTime(), patNo, times, ledgerSn);
        return ResultVoUtil.success(zy);
    }

    private void setDrgInfo(ZyInactpatient zy, Date admTime, String patNo, Integer times, Integer ledgerSn) {
        SiSetlinfoTemp siSetlinfoTemp = dao.countZy(patNo, times) == null ? dao.getJieSuanDetail(patNo, times, ledgerSn, ZyActpatient.ZY_INACTPATIENT) : dao.getJieSuanDetail(patNo, times, ledgerSn, ZyActpatient.ZY_ACTPATIENT);
        SetlinfoUpld setlinfoUpld = new SetlinfoUpld();
        dealSetlinfoUpld(patNo, times, setlinfoUpld);
        BaseInfo bf = new BaseInfo();
        String visitId = StrUtil.format("{}_{}_{}", patNo, times, ledgerSn);
        bf.setVisitId(visitId)
                .setGend(siSetlinfoTemp.getGend())
                .setBrdy(DateUtil.formatDatetime(siSetlinfoTemp.getBrdy(), "yyyy-MM-dd"))
                .setAge(siSetlinfoTemp.getAge() == null ? "" : String.valueOf(siSetlinfoTemp.getAge().intValue()))
                .setNwbAge(setlinfoUpld.getNwbAge())
                .setNwbBirWt(setlinfoUpld.getNwbBirWt())
                .setNwbAdmWt(setlinfoUpld.getNwbAdmWt())
                .setAdmTime(admTime)
                .setActIptDays(siSetlinfoTemp.getActIptDays())
                .setTotalFee(siSetlinfoTemp.getMedfeeSumamt())
                .setCdntnPay("")
                .setIllPay("");
        JSONObject upload = new JSONObject();
        upload.put("base_info", bf);
        upload.put("dise_info_list", getDrgDisList(CollUtil.isNotEmpty(zy.getNewYbZyDisDiag()) ? zy.getNewYbZyDisDiag() : zy.getYbZyDisDiag(), visitId));
        upload.put("oprt_info_list", getOprtInfoList(siSetlinfoTemp.getAuditFlag() == null ? zy.getBatjBa4() : zy.getNewBatjBa4(), visitId));
        try {
            log.info("drg分组传参:{}", JSON.toJSONString(upload));
            JSONObject res = drgWebApi.getDrgCaseQualityControlGroup(upload);
            log.info("drg分组结果:{}", JSON.toJSONString(res));
            if (res.getInteger("code") == 0) {
                if (res.getJSONObject("result") != null) {
                    JSONArray groupInfo = res.getJSONObject("result").getJSONArray("group_info");
                    if (groupInfo != null) {
                        JSONObject item = groupInfo.getJSONObject(0);
                        TUploadDrgGroup drgGroupInfo = new TUploadDrgGroup();
                        drgGroupInfo.setCode(item.getString("code"));
                        drgGroupInfo.setName(item.getString("name"));
                        drgGroupInfo.setWeight(item.getBigDecimal("weight"));
                        drgGroupInfo.setBl(item.getString("bl"));
                        drgGroupInfo.setProfit(item.getBigDecimal("profit"));
                        drgGroupInfo.setFeeStand(item.getBigDecimal("fee_stand"));
                        zy.setDrgGroupInfo(drgGroupInfo);
                    }
                }
            }
        } catch (Exception e) {
            log.error("调用创智分组期报错", e);
        }
    }

    private List<OprtInfoList> getOprtInfoList(List<BatjBa4> batjBa4s, String visitId) {
        List<OprtInfoList> oprtInfoList = new ArrayList<>();
        if (CollUtil.isEmpty(batjBa4s)) return oprtInfoList;
        for (int i = 0; i < batjBa4s.size(); i++) {
            OprtInfoList oprtInfo = new OprtInfoList();
            oprtInfo.setSortNo(String.valueOf(i + 1));
            oprtInfo.setVisitId(visitId);
            oprtInfo.setOprnOprtCode(batjBa4s.get(i).getSsbm());
            oprtInfo.setOprnOprtName(batjBa4s.get(i).getSsmc());
            oprtInfo.setOprnOprtType(i == 0 ? "1" : "2");
            oprtInfoList.add(oprtInfo);
        }
        return oprtInfoList;
    }

    private List<DiseInfoList> getDrgDisList(List<YbZyDisDiag> ybZyDisDiagList, String visitId) {
        List<DiseInfoList> diseInfoListList = new ArrayList<DiseInfoList>();
        if (CollUtil.isEmpty(ybZyDisDiagList)) return diseInfoListList;
        for (int i = 0; i < ybZyDisDiagList.size(); i++) {
            DiseInfoList diseInfo = new DiseInfoList();
            diseInfo.setMaindiagFlag(i == 0 ? "1" : "0");
            diseInfo.setDiagCode(ybZyDisDiagList.get(i).getDisDiag());
            diseInfo.setDiagName(ybZyDisDiagList.get(i).getDisDiagComment());
            diseInfo.setVisitId(visitId);
            diseInfo.setSortNo(String.valueOf(i + 1));
            diseInfoListList.add(diseInfo);
        }
        return diseInfoListList;
    }


    /**
     * @description:取病案首页的诊断
     * @author: lihong
     * @date: 2023/3/9 10:07
     * @param: patNo
     * @param: times
     **/
    private List<YbZyDisDiag> getPatienYbZyDisDiag(String patNo, Integer times) {
        //判断签收诊断是否有诊断信息
        Integer exist = dao.exisCaseSheetDis(patNo, times);
        List<YbZyDisDiag> ybZyDisDiags;
        if (exist == null) {
            ybZyDisDiags = dao.getBafirstPage1(patNo, times);
        } else {
            ybZyDisDiags = dao.getCaseSheetDis(patNo, times);
        }
        if (CollUtil.isEmpty(ybZyDisDiags)) {
            ybZyDisDiags = dao.zhenDuanXinXi(patNo, times, "zy_dis_diag_yb");
        }
        return ybZyDisDiags;
    }

    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) {
        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, "入院病情不能为空。");
                }
            }
        }
        log.info("手术信息：{}", JSON.toJSONString(param.getBatjBa4()));
        SetlinfoUpld setlinfoUpld = getSetlinfoUpld5(param.getInpatientNo(), param.getAdmissTimes(), param.getLedgerSn());
        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, String.format("手术：【%s】，手术日期不能为空", item.getSsmc()));
                } else {
                    if (item.getSsrq() != null && !cn.hutool.core.date.DateUtil.isIn(item.getSsrq(), cn.hutool.core.date.DateUtil.offsetDay(setlinfoUpld.getAdmTime(), -1), setlinfoUpld.getDscgTime())) {
                        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("手术：【%s】，手术日期应在出入院时间范围内", item.getSsmc()));
                    }
                }
                if (StringUtil.isBlank(item.getSsys())) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("手术：【%s】，手术医生不能为空", item.getSsmc()));
                } else {
                    String ybCodeMessage = validateYbCode(item.getSsys()).getData();
                    if (StringUtil.notBlank(ybCodeMessage)) {
                        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("手术：【%s】，手术医生，%s", item.getSsmc(), ybCodeMessage));
                    }
                }
                if (StringUtil.notBlank(item.getMzys())) {
                    String ybCodeMessage = validateYbCode(item.getMzys()).getData();
                    if (StringUtil.notBlank(ybCodeMessage)) {
                        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("手术：【%s】，麻醉医生，%s", item.getSsmc(), ybCodeMessage));
                    }
                }
                if (StringUtil.isBlank(item.getSsmc())) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("手术：【%s】，手术名称不能为空", item.getSsmc()));
                }
                if (StringUtil.isBlank(item.getSsbm())) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("手术：【%s】，手术编码不能为空", item.getSsmc()));
                }
                if (StringUtil.isBlank(item.getSsjb()) && dao.countZlAndZd(item.getSsbm()) == 0) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("手术：【%s】，手术级别不能为空", item.getSsmc()));
                }
                if ((StringUtil.isBlank(item.getQkjb()) || StringUtil.isBlank(item.getYhqk())) && dao.countZlAndZd(item.getSsbm()) == 0) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("手术：【%s】，切口愈合等级不能为空", item.getSsmc()));
                }
                if (StringUtil.notBlank(item.getMzys())) {
                    if (item.getAnstStartDate() == null || item.getAnstEndDate() == null) {
                        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("手术：【%s】，麻醉医生不为空,麻醉开始时间,麻醉结束时间不能为空", item.getSsmc()));
                    }
                }
                //局部麻醉可以为空,其他需要麻醉时间
                if (StringUtil.notBlank(item.getMzff()) && !item.getMzff().equals("29") && !item.getMzff().equals("23")) {
                    if (item.getAnstStartDate() == null || item.getAnstEndDate() == null || StringUtil.isBlank(item.getMzys())) {
                        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("手术：【%s】，麻醉方式不为空,麻醉开始时间,麻醉结束时间,麻醉医生不能为空", item.getSsmc()));
                    }
                }
                List<String> a = VerifyCaseFrontSheet.logicalSurgeryTime(setlinfoUpld.getAdmTime(), setlinfoUpld.getDscgTime(),
                        item.getOpStartDate(), item.getOpEndDate(), item.getAnstStartDate(), item.getAnstEndDate());
                if (ListUtil.notBlank(a)) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("手术：【%s】，%s", item.getSsmc(), a));
                }
                //手术或麻醉时间可以在入院时间前一天内
                if (item.getOpStartDate() != null && !cn.hutool.core.date.DateUtil.isIn(item.getOpStartDate(), cn.hutool.core.date.DateUtil.offsetDay(setlinfoUpld.getAdmTime(), -1), setlinfoUpld.getDscgTime())) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("手术：【%s】，手术开始时间应在出入院时间范围内", item.getSsmc()));
                }

                if (item.getOpEndDate() != null && !cn.hutool.core.date.DateUtil.isIn(item.getOpEndDate(), cn.hutool.core.date.DateUtil.offsetDay(setlinfoUpld.getAdmTime(), -1), setlinfoUpld.getDscgTime())) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("手术：【%s】，手术结束时间应在出入院时间范围内", item.getSsmc()));
                }

                if (item.getAnstStartDate() != null && !cn.hutool.core.date.DateUtil.isIn(item.getAnstStartDate(), cn.hutool.core.date.DateUtil.offsetDay(setlinfoUpld.getAdmTime(), -1), setlinfoUpld.getDscgTime())) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("手术：【%s】，麻醉开始时间应在出入院时间范围内", item.getSsmc()));
                }

                if (item.getAnstEndDate() != null && !cn.hutool.core.date.DateUtil.isIn(item.getAnstEndDate(), cn.hutool.core.date.DateUtil.offsetDay(setlinfoUpld.getAdmTime(), -1), setlinfoUpld.getDscgTime())) {
                    return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, String.format("手术：【%s】，麻醉结束时间应在出入院时间范围内", item.getSsmc()));
                }

                PublicServer.surgeryTimeLimit(item.getSsmc(), item.getOpStartDate(), item.getOpEndDate(), item.getAnstStartDate(), item.getAnstEndDate());
            }
        }
        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, "不可以有相同的诊断。");
        }

        //表示超级审核权限可以直接保存并申请审核通过
        SetlAuditLog setlAuditLog;
        if ("1".equals(param.getSaveAuditPassFlag())) {
            TYbSetlModifyReq tYbSetlModifyReq = dao.getSetlModifyReq(param.getInpatientNo(), param.getAdmissTimes());
            dao.delDiseAndOprt(param.getInpatientNo(), param.getAdmissTimes());
            if (tYbSetlModifyReq != null && tYbSetlModifyReq.getId() != null) {
                dao.updateReq(tYbSetlModifyReq.getId(), "审核通过", TokenUtil.getInstance().getTokenUserId(), param.getOpIdName());
                dao.upAuditFlag(tYbSetlModifyReq.getId(), 1);
            } else {
                TYbSetlModifyReq insertData = new TYbSetlModifyReq();
                insertData.setPatNo(param.getInpatientNo());
                insertData.setTimes(param.getAdmissTimes());
                insertData.setReqOpId(TokenUtil.getInstance().getTokenUserId());
                insertData.setReqOpName(param.getOpIdName());
                insertData.setReqOpDate(new Date());
                insertData.setReqRemark(StringUtil.notBlank(param.getReqRemark()) ? param.getReqRemark() : "直接审核通过");
                insertData.setAuditStaff(TokenUtil.getInstance().getTokenUserId());
                insertData.setAuditName(param.getOpIdName());
                insertData.setAuditDate(new Date());
                insertData.setAuditRemark("审核通过");
                insertData.setAuditFlag(1);
                dao.insertSetlModifyReq(insertData);
            }
            //记录审核日志
            setlAuditLog = cretaSetlAuditLog(param, TokenUtil.getInstance().getTokenUserId(), 1, 1);
        } else {
            setlAuditLog = sendReq(0, 0, param);
        }
        saveAuditLog(setlAuditLog);
        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());
        if (!"1".equals(param.getSaveAuditPassFlag())) {
            tSetlDeptConfService.asynSendAuditMessge(param.getDisDept(), param.getOutDeptName(), param.getName(), param.getInpatientNo());
        }
        SiSetlinfoTemp setlInfo = dao.getSetTimeAndSetListId(param.getInpatientNo(), param.getAdmissTimes(), param.getLedgerSn());
        //已上传数据重新进行上传
        reUpload(param.getInpatientNo(), param.getAdmissTimes(), param.getLedgerSn(), setlInfo.getSetlTime(), setlInfo.getSetlListId());
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "保存成功。");
    }

    public SetlinfoUpld getSetlinfoUpld5(String patNo, Integer times, Integer ledgerSn) {
        if (dao.countZy(patNo, times) == null) {
            return dao.setlinfo5(patNo, times, ledgerSn, ZyActpatient.ZY_INACTPATIENT);
        } else {
            return dao.setlinfo5(patNo, times, ledgerSn, ZyActpatient.ZY_ACTPATIENT);
        }
    }


    //发起审核 返回日志
    public SetlAuditLog sendReq(Integer auditFlag, Integer auditType, ZyInactpatient param) {
        //发起审核
        dao.delReq(param.getInpatientNo(), param.getAdmissTimes());
        dao.setlModifyReq(param.getInpatientNo(), param.getAdmissTimes(), TokenUtil.getInstance().getTokenUserId(), param.getOpIdName(), param.getReqRemark());
        //记录审核日志
        SetlAuditLog setlAuditLog = cretaSetlAuditLog(param, TokenUtil.getInstance().getTokenUserId(), auditFlag, auditType);
        return setlAuditLog;
    }

    private SetlAuditLog cretaSetlAuditLog(ZyInactpatient param, String tokenUserId, Integer auditFlag, Integer auditType) {
        SetlAuditLog setlAuditLog = new SetlAuditLog();
        setlAuditLog.setPatNo(param.getInpatientNo());
        setlAuditLog.setTimes(param.getAdmissTimes());
        setlAuditLog.setRemark(param.getReqRemark());
        setlAuditLog.setCreateCode(tokenUserId);
        setlAuditLog.setCreateName(param.getOpIdName());
        setlAuditLog.setAuditFlag(auditFlag);
        setlAuditLog.setAuditType(auditType);
        return setlAuditLog;
    }

    @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());
            saveAuditLog(id, auditFlag, remark, auditStaff, auditName, req);
            return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "审核已通过 (*^▽^*)");
        }
        if (StringUtil.isBlank(remark)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "驳回信息不能为空。");
        }
        //驳回
        //审核 并 保存审核日志
        saveAuditLog(id, auditFlag, remark, auditStaff, auditName, req);
        try {
            sendWxInfoService.sendCorpWxMsg(dao.yuanGongGongHao(req.getReqOpId()), String.format("医保结算单上传\n申请已驳回\n患者姓名：【%s】\n住院号：【%s】\n原因：【%s】\n审核人：【%s】", req.getPatName(), req.getPatNo(), remark, auditName));
        } catch (Exception e) {
            log.error("审核已驳回推送企业微信报错", e);
        }
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "审核已驳回 (╯﹏╰)b");
    }

    private void saveAuditLog(Integer id, Integer auditFlag, String remark, String auditStaff, String auditName, TYbSetlModifyReq req) {
        dao.updateReq(id, remark, auditStaff, auditName);
        dao.upAuditFlag(id, auditFlag);
        SetlAuditLog setlAuditLog = new SetlAuditLog();
        setlAuditLog.setPatNo(req.getPatNo());
        setlAuditLog.setTimes(req.getTimes());
        setlAuditLog.setAuditType(1);
        setlAuditLog.setAuditFlag(auditFlag);
        setlAuditLog.setRemark(remark);
        setlAuditLog.setCreateCode(auditStaff);
        setlAuditLog.setCreateName(auditName);
        saveAuditLog(setlAuditLog);
    }

    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_EL_MESSAGE, "设置成功 (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.getInstance().getTokenUserId(), patNo, times, code);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "管床医生修改成功。");
    }

    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));
    }

    /**
     * 门诊患者结算单信息
     *
     * @param patNo    门诊号
     * @param times    次数
     * @param ledgerSn 账页号
     * @return 返回门诊
     * @throws Exception
     */
    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);
        if (StringUtil.notBlank(mzPatient.getChfpdrCode())) {
            String ybCode = getYbCode(mzPatient.getChfpdrCode());
            mzPatient.setChfpdrCode(ybCode);
        }
        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.getInstance().getTokenUserId());
        // 医疗机构填报人
        mzPatient.setMedinsFillPsn(getDropdownBox.getName());
        // 医疗机构填报部门
        mzPatient.setMedinsFillDept(getDropdownBox.getDeptName());
        // 票据号码
        String billNo = dao.mzBillNo(patNo, times);
        mzPatient.setBillNo(StringUtil.isBlank(billNo) ? RandomUtil.randomNumbers(8) : billNo);
        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());
            }
        }
        //联系人处理
        if (StringUtil.isBlank(mzPatient.getConerAddr()) || StringUtil.isBlank(mzPatient.getConerTel())) {
            mzPatient.setConerName(null);
            mzPatient.setConerAddr(null);
            mzPatient.setConerTel(null);
            mzPatient.setPatnRlts(null);
        }

        List<String> urbanAndRuralMedicalInsurance = Arrays.asList("390", "392");
        // 城乡医保类型可不填这两项
        if (urbanAndRuralMedicalInsurance.contains(mzPatient.getHiType())) {
            mzPatient.setEmpTel(null);
            mzPatient.setPoscode(null);
            mzPatient.setEmpName(null);
            mzPatient.setEmpAddr(null);
        }
        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_EL_MESSAGE, "修改成功。");
    }

    /**
     * 添加或修改输血量
     * 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_EL_MESSAGE);
    }

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

    public void exportAutoUploadInfo(HttpServletResponse response, AutoUploadBill query) {
        query.setCurrentPage(1);
        query.setPageSize(100000);
        IPage<AutoUploadBill> autoUploadBillIPage = autoUploadBillService.queryPage(query);
        List<AutoUploadBill> list = autoUploadBillIPage.getRecords();
        if (ListUtil.isBlank(list)) {
            throw new BizException(ExceptionEnum.INTERNAL_SERVER_ERROR, "没有查到数据");
        }
        List<Map<String, Object>> result = ExcelUtil.beanToMap(list, AutoUploadBill.class);
        String[] display = {"住院号", "姓名", "住院次数", "账页号", "出院科室", "医疗类别", "参保地", "清算机构", "上传类型", "上传人", "上传结果标识", "上传时间", "患者结算时间", "日志"};
        String[] names = {"patNo", "psnName", "times", "ledgerSn", "outDeptName", "medTypeName", "insuplcAdmdvsName", "clrOptinsName", "typeFlagName", "uploadName", "flagName", "createdDate", "setlTime", "logText"};
        List<HeadInfo> headList = ExcelUtil.createHeadInfos(display, names);
        ExcelUtil.exportExcelReport(response, result, headList, "上传日志");

    }

    /**
     * @description:drg分组测算
     * @author: lihong
     * @date: 2022/12/8 11:13
     * @param: param
     * @return: thyyxxk.webserver.entity.ResultVo<java.lang.String>
     **/
    public ResultVo<String> drgGroupTest(ZyInactpatient param) {
        SetlinfoUpld setlinfo1 = dao.setlinfo1(param.getInpatientNo(), param.getAdmissTimes(), param.getLedgerSn());
        dealSetlinfoUpld(param.getInpatientNo(), param.getAdmissTimes(), setlinfo1);
        SetlinfoUpld setlinfo2 = getSetlinfoUpld2(param.getInpatientNo(), param.getAdmissTimes());
        SetlinfoUpld setlinfo5 = getSetlinfoUpld5(param.getInpatientNo(), param.getAdmissTimes(), param.getLedgerSn());
        BeanUtil.copyProperties(setlinfo2, setlinfo1, CopyOptions.create().setIgnoreNullValue(true));
        BeanUtil.copyProperties(setlinfo5, setlinfo1, CopyOptions.create().setIgnoreNullValue(true));
        DrgGroupTestVO drgGroupTestVO = createDrgGroupTestVO(param, setlinfo1);
        log.info("调用诊断辅助入参:{}", JSON.toJSONString(drgGroupTestVO));
        try {
            ResultVo<String> res = drgWebApi.getDrgIntelligentGrouping(JSON.parseObject(JSON.toJSONString(drgGroupTestVO)));
            log.info("调用诊断辅助返回结果:{}", res);
            return res;
        } catch (Exception e) {
            log.error("调用诊断辅助填报接口报错", e);
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "调用诊断辅助填报接口报错");
        }
    }

    private DrgGroupTestVO createDrgGroupTestVO(ZyInactpatient param, SetlinfoUpld setlinfoUpld) {
        DrgGroupTestVO drgGroupTestVO = new DrgGroupTestVO();
        drgGroupTestVO.setVisit_id(param.getInpatientNo() + "_" + param.getAdmissTimes());    //就诊ID
        drgGroupTestVO.setXm(param.getName());    //姓名
        drgGroupTestVO.setBah(param.getInpatientNo());    //病案号
        drgGroupTestVO.setCysj(DateUtil.formatDatetime(setlinfoUpld.getDscgTime(), "yyyy-MM-dd"));    //出院时间
        drgGroupTestVO.setXb(param.getSex());    //性别
        drgGroupTestVO.setNl(setlinfoUpld.getAge());    //年龄
        drgGroupTestVO.setZfy(param.getMedfeeSumamt().toString());   //总费用
        drgGroupTestVO.setSjzyts(param.getActIptDays());    //实际住院天数

        drgGroupTestVO.setRytj(setlinfoUpld.getAdmWay());    //入院途径
        drgGroupTestVO.setLyfs(setlinfoUpld.getDscgWay());    //	离院方式
        drgGroupTestVO.setInsur_type_id(StringUtil.isBlank(setlinfoUpld.getHiType()) ? "" : !"310".equals(setlinfoUpld.getHiType()) && !"390".equals(setlinfoUpld.getHiType()) ? "390" : setlinfoUpld.getHiType());    //	病人险种
        drgGroupTestVO.setXsecstz(setlinfoUpld.getNwbBirWt());    //	新生儿出生体重(克)
        drgGroupTestVO.setXserytz(setlinfoUpld.getNwbAdmWt());    //新生儿入院体重(克)
        drgGroupTestVO.setBzyzsnl(setlinfoUpld.getNwbAge());    //不足一周岁年龄(天)
        // 封装诊断
        if (ListUtil.notBlank(param.getNewYbZyDisDiag())) {
            drgGroupTestVO.setRybq(param.getNewYbZyDisDiag().get(0).getAdmissCond() == null ? "" : param.getNewYbZyDisDiag().get(0).getAdmissCond().toString());//入院病情
            drgGroupTestVO.setJbdm(param.getNewYbZyDisDiag().get(0).getDisDiag());
            drgGroupTestVO.setZyzd(param.getNewYbZyDisDiag().get(0).getDisDiagComment());
            convertToQtzdList(CollUtil.sub(param.getNewYbZyDisDiag(), 1, param.getNewYbZyDisDiag().size()), drgGroupTestVO);
            //setFieldValue(drgGroupTestVO, "jbdm", "disDiag", param.getNewYbZyDisDiag(), 1, 16);
        }
        // 封装手术
        if (ListUtil.notBlank(param.getNewBatjBa4())) {
            drgGroupTestVO.setSsjczbm1(param.getNewBatjBa4().get(0).getSsbm());
            drgGroupTestVO.setSsjczmc1(param.getNewBatjBa4().get(0).getSsmc());
            convertToSsjczList(CollUtil.sub(param.getNewBatjBa4(), 1, param.getNewBatjBa4().size()), drgGroupTestVO);
            //setFieldValue(drgGroupTestVO, "ssjczbm", "ssbm", param.getNewBatjBa4(), 2, 7);
        }
        return drgGroupTestVO;
    }

    private void convertToSsjczList(List<BatjBa4> newBatjBa4, DrgGroupTestVO drgGroupTestVO) {
        if (CollUtil.isEmpty(newBatjBa4)) return;
        List<Map<String, Object>> ssList = new ArrayList<>();
        for (BatjBa4 item : newBatjBa4) {
            Map<String, Object> itemMap = new HashMap<>();
            itemMap.put("ssjczbm", item.getSsbm());
            itemMap.put("ssjczmc", item.getSsmc());
            ssList.add(itemMap);
        }
        drgGroupTestVO.setSsjczList(ssList);
    }

    private void convertToQtzdList(List<YbZyDisDiag> ybZyDisDiagList, DrgGroupTestVO drgGroupTestVO) {
        if (CollUtil.isEmpty(ybZyDisDiagList)) return;
        List<Map<String, Object>> zdList = new ArrayList<>();
        for (YbZyDisDiag item : ybZyDisDiagList) {
            Map<String, Object> itemMap = new HashMap<>();
            itemMap.put("qtzddm", item.getDisDiag());
            itemMap.put("qtzdmc", item.getDisDiagComment());
            zdList.add(itemMap);
        }
        drgGroupTestVO.setQtzdList(zdList);
    }

    private <T> void setFieldValue(DrgGroupTestVO drgGroupTestVO, String fieldName, String targetFieldName, List<T> classList, Integer initSize, int maxSize) {
        if (ListUtil.isBlank(classList)) return;
        if (initSize == null) {
            initSize = 0;
        }
        for (int i = 1; i < classList.size(); i++) {
            if (i >= maxSize) {
                break;
            }
            Object fieldValue = ReflectUtil.getFieldValue(classList.get(i), targetFieldName);
            ReflectUtil.setFieldValue(drgGroupTestVO, fieldName + initSize, fieldValue);
            ++initSize;
        }
    }

    /**
     * @description: 发起审核
     * @author: lihong
     * @date: 2022/12/12 16:28
     * @param: setlAuditLog
     * @return: thyyxxk.webserver.entity.ResultVo<java.lang.String>
     **/
    public ResultVo<String> sendAudit(SetlAuditLog setlAuditLog) {
        try {
            //只有 驳回 或没有审核记录 才能 发起申请
            Integer auditFlag = dao.getAuditFlag(setlAuditLog.getPatNo(), setlAuditLog.getTimes());
            if (auditFlag == null || auditFlag == 2) {
                dao.deleteModifReq(setlAuditLog.getPatNo(), setlAuditLog.getTimes());
                dao.setlModifyReq(setlAuditLog.getPatNo(), setlAuditLog.getTimes(), TokenUtil.getInstance().getTokenUserId(), setlAuditLog.getCreateName(), setlAuditLog.getRemark());
                saveAuditLog(setlAuditLog);
            } else {
                throw new BizException(ExceptionEnum.LOGICAL_ERROR, "只有驳回状态或未申请状态才能发起审核流程");
            }
        } catch (Exception e) {
            log.error("发起审核失败", e);
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "发起审核失败");
        }
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "成功");
    }

    private void saveAuditLog(SetlAuditLog setlAuditLog) {
        if (setlAuditLog.getAuditType() == null) {
            setlAuditLog.setAuditType(0);
        }
        if (StringUtil.isBlank(setlAuditLog.getRemark())) {
            setlAuditLog.setRemark("申请审核");
        }
        if (setlAuditLog.getAuditFlag() == null) {
            //设置为待审核
            setlAuditLog.setAuditFlag(0);
        }
        if (StringUtil.isBlank(setlAuditLog.getCreateCode())) {
            String code = TokenUtil.getInstance().getTokenUserId();
            setlAuditLog.setCreateCode(code);
            setlAuditLog.setCreateName(publicServer.huoQuYuanGongXinXi(code).getName());
        }
        log.info("审核参数setlAuditLog:{}", JSON.toJSONString(setlAuditLog));
        dao.insertSetlAuditLog(setlAuditLog);
    }

    /**
     * @description:获取审核日志
     * @author: lihong
     * @date: 2022/12/13 9:04
     * @param: patNo
     * @param: times
     * @return: thyyxxk.webserver.entity.ResultVo<java.lang.String>
     **/
    public ResultVo<List<SetlAuditLog>> listSetlAuditLog(String patNo, Integer times) {
        AssertUtil.isnotBlank(patNo, "病案号不能为空");
        AssertUtil.isnotBlank(times, "住院次数不能为空");
        List<SetlAuditLog> setlAuditLogs = dao.listSetlAuditLog(patNo, times);
        return ResultVoUtil.success(setlAuditLogs);
    }

    /**
     * @description:结算清单质控测算
     * @author: lihong
     * @date: 2022/12/14 15:09
     * @param: param
     * @return: thyyxxk.webserver.entity.ResultVo<java.lang.String>
     **/
    public ResultVo<List<QualityInfoVO>> drgQualityTest(ZyInactpatient param) {
        List<QualityInfoVO> qualityInfoVOS;
        SiLog siLog = new SiLog(exec.makeMsgId(), SiFunction.QUALITY_INFO.getCode(), null,
                TokenUtil.getInstance().getTokenUserId(), null, null, param.getInpatientNo(), param.getAdmissTimes(), param.getLedgerSn(), 1, null);
        try {
            SetlinfoUpld setlinfoUpldInfo = getSetlinfoUpldInfo(param.getInpatientNo(), param.getAdmissTimes(), param.getLedgerSn());
            siLog.setInsuplcAdmdvs(setlinfoUpldInfo.getInsuplc());
            siLog.setPsnNo(setlinfoUpldInfo.getPsnNo());
            AssertUtil.isnotBlank(setlinfoUpldInfo, "结算清单基本信息为空");
            Map<String, Object> tempResult = getDrgQualityResult(param, setlinfoUpldInfo);
            JSONObject resultInfo = (JSONObject) tempResult.get("result");
            Object qualityParam = tempResult.get("param");
            log.info("质控测算返回:{}", JSON.toJSONString(resultInfo));
            siLog.setBody(JSON.toJSONString(qualityParam));
            siLog.setResult(JSON.toJSONString(resultInfo));
            if (resultInfo.getBooleanValue("isSuccess")) {
                siLog.setInfcode(0);
                JSONArray jsonArray = resultInfo.getJSONObject("result").getJSONArray("quality_info");
                siLogService.delAndSave(siLog);
                if (jsonArray.isEmpty()) {
                    return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "没有质控问题数据");
                }
                List<QualityInfoVO> temp = JSON.parseArray(JSON.toJSONString(jsonArray), QualityInfoVO.class);
                qualityInfoVOS = temp.stream().filter(obj -> !"disease_name".equals(obj.getField_id())).collect(Collectors.toList());
                if (ListUtil.isBlank(qualityInfoVOS)) {
                    return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "没有质控问题数据");
                }
            } else {
                siLog.setInfcode(-1);
                siLog.setBody("{\"errMsg\":\"质控测算报错\"}");
                siLogService.delAndSave(siLog);
                throw new BizException(ExceptionEnum.LOGICAL_ERROR, "创智质控测算接口调用失败");
            }

        } catch (Exception e) {
            siLog.setInfcode(-1);
            siLog.setBody("{\"errMsg\":\"质控测算报错\"}");
            siLogService.delAndSave(siLog);
            if (e instanceof BizException) {
                throw new BizException(ExceptionEnum.LOGICAL_ERROR, e.getMessage());
            } else {
                log.error("质控测算报错", e);
                throw new BizException(ExceptionEnum.LOGICAL_ERROR, "质控测算报错");
            }
        }
        return ResultVoUtil.success(qualityInfoVOS);
    }

    public Map<String, Object> getDrgQualityResult(ZyInactpatient param, SetlinfoUpld setlinfoUpldInfo) {
        Map<String, Object> resultMap = new HashMap<>();
        String visitId = param.getInpatientNo() + "_" + param.getAdmissTimes();
        Map<String, Object> tempMap = BeanUtil.beanToMap(setlinfoUpldInfo, true, true);
        SetlBaseInfoVO setlBaseInfoVO = new SetlBaseInfoVO();
        Map<String, Object> drgQualityParam = new HashMap<>();
        BeanUtil.fillBeanWithMap(tempMap, setlBaseInfoVO, true);
        setlBaseInfoVO.setVisit_id(visitId);
        setlBaseInfoVO.setFixmedins_code("H32132200561");
        setlBaseInfoVO.setFixmedins_name("沭阳铭和医院");
        setlBaseInfoVO.setTotal_fee(param.getMedfeeSumamt() == null ? null : param.getMedfeeSumamt().toString());
        //格式化一些时间的问题
        formatSetlBaseInfoVO(setlBaseInfoVO, setlinfoUpldInfo);

        log.info("setlBaseInfoVO 基本信息传参:{}", JSON.toJSONString(setlBaseInfoVO));
        drgQualityParam.put("base_info", setlBaseInfoVO);
        //诊断
        //先诊断转码 国临 转医保
        if (ListUtil.notBlank(param.getNewYbZyDisDiag())) {
            List<String> disCode = param.getNewYbZyDisDiag().stream().map(YbZyDisDiag::getDisDiag).collect(Collectors.toList());
            List<Map<String, String>> ybDisCodes = dao.listYbDiseOrOprt(disCode, "zd_icd_code_new");
            List<DiseInfoListVO> diseInfoListVOS = ConvertUtil.ybZyDisDiag2DiseInfoListVO(param.getNewYbZyDisDiag(), visitId, ybDisCodes);
            drgQualityParam.put("dise_info_list", diseInfoListVOS);
        } else {
            drgQualityParam.put("dise_info_list", new ArrayList<>(1));
        }
        //手术
        if (ListUtil.notBlank(param.getNewBatjBa4())) {
            List<String> oprtCodes = param.getNewBatjBa4().stream().map(BatjBa4::getSsbm).collect(Collectors.toList());
            List<Map<String, String>> ybOprtCodes = dao.listYbDiseOrOprt(oprtCodes, "zd_icd9_cm3");
            List<String> mzfsCodes = param.getNewBatjBa4().stream().map(BatjBa4::getMzff).collect(Collectors.toList());
            List<Map<String, String>> ybMzfs = dao.listZdAnaesthesia(mzfsCodes);
            List<String> ssysCodes = param.getNewBatjBa4().stream().map(BatjBa4::getSsys).collect(Collectors.toList());
            List<String> mzysCodes = param.getNewBatjBa4().stream().map(BatjBa4::getMzys).collect(Collectors.toList());
            if (ListUtil.notBlank(mzysCodes)) {
                ssysCodes.addAll(mzysCodes);
            }
            //医生转码
            List<Map<String, String>> ysCodeDict = dao.listYbSsys(ssysCodes);
            List<OprtInfoListVO> oprtInfoListVOS = ConvertUtil.batjBa4ToOprtInfoListVO(param.getNewBatjBa4(), visitId, ybOprtCodes, ybMzfs, ysCodeDict);
            drgQualityParam.put("oprt_info_list", oprtInfoListVOS);
        } else {
            drgQualityParam.put("oprt_info_list", new ArrayList<>(1));
        }
        log.info("质控测算传参:{}", JSON.toJSONString(drgQualityParam));
        JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(drgQualityParam));
        JSONObject result = drgWebApi.drgQuality(jsonObject);
        resultMap.put("result", result);
        resultMap.put("param", drgQualityParam);
        return resultMap;
    }

    private void formatSetlBaseInfoVO(SetlBaseInfoVO setlBaseInfoVO, SetlinfoUpld setlinfoUpldInfo) {
        String timepatten = "yyyy-MM-dd HH:mm:ss";
        setlBaseInfoVO.setAge(StringUtil.notBlank(setlinfoUpldInfo.getAge()) ? String.valueOf(new BigDecimal(setlinfoUpldInfo.getAge()).intValue()) : null);
        setlBaseInfoVO.setDcla_time(DateUtil.formatDatetime(setlinfoUpldInfo.getDscgTime(), timepatten));
        setlBaseInfoVO.setDscg_time(DateUtil.formatDatetime(setlinfoUpldInfo.getDscgTime(), timepatten));
        setlBaseInfoVO.setAdm_time(DateUtil.formatDatetime(setlinfoUpldInfo.getAdmTime(), timepatten));
        setlBaseInfoVO.setOpsp_mdtrt_date(DateUtil.formatDatetime(setlinfoUpldInfo.getOpspMdtrtDate(), timepatten));
        setlBaseInfoVO.setSetl_begn_date(DateUtil.formatDatetime(setlinfoUpldInfo.getSetlBegnDate(), timepatten));
        setlBaseInfoVO.setSetl_end_date(DateUtil.formatDatetime(setlinfoUpldInfo.getSetlEndDate(), timepatten));
        setlBaseInfoVO.setResp_nurs(setlinfoUpldInfo.getRespNursName());
    }


    private SetlinfoUpld getSetlinfoUpldInfo(String patNo, Integer times, Integer ledgerSn) throws Exception {
        SetlinfoUpld setlinfoUpld = dao.setlinfo1(patNo, times, ledgerSn);
        dealSetlinfoUpld(patNo, times, setlinfoUpld);

        if (dao.countZy(patNo, times) == null) {
            EntityCopy.Copy(getSetlinfoUpld2(patNo, times), setlinfoUpld);
        } else {
            EntityCopy.Copy(getSetlinfoUpld2(patNo, times), setlinfoUpld);
        }
        if (StringUtil.isBlank(setlinfoUpld.getRespNursCode())) {
            setRespNurs(setlinfoUpld, patNo, times);
        }
        EntityCopy.Copy(dao.setlinfo3(String.format("inpatient_no ='%s'", patNo)), setlinfoUpld);
        EntityCopy.Copy(dao.setlinfo4(patNo, times), setlinfoUpld);
        EntityCopy.Copy(getSetlinfoUpld5(patNo, times, ledgerSn), setlinfoUpld);

        if (patNo.startsWith("JT")) {
            EntityCopy.Copy(dao.countZy(patNo, times) == null ? dao.singleDiseasePatientInformation(patNo, times, ZyActpatient.ZY_INACTPATIENT) : dao.singleDiseasePatientInformation(patNo, times, ZyActpatient.ZY_ACTPATIENT), setlinfoUpld);
        }
        // 特级护理
        setlinfoUpld.setSpgaNurscareDays(nursingDays(dao.teJiHuLi(publicServer.getInpatientNo(patNo), times, ledgerSn, PublicServer.getInfantFlag(patNo))));
        // 一级护理
        setlinfoUpld.setLv1NurscareDays(nursingDays(dao.yiJiHuLi(publicServer.getInpatientNo(patNo), times, ledgerSn, PublicServer.getInfantFlag(patNo))));
        // 二级护理
        setlinfoUpld.setScdNurscareDays(nursingDays(dao.erJiHuLi(publicServer.getInpatientNo(patNo), times, ledgerSn, PublicServer.getInfantFlag(patNo))));
        // 三级护理
        setlinfoUpld.setLv3NurscareDays(nursingDays(dao.sanJiHuLi(publicServer.getInpatientNo(patNo), times, ledgerSn, PublicServer.getInfantFlag(patNo))));
        GetDropdownBox getDropdownBox = dao.userInfo(TokenUtil.getInstance().getTokenUserId());
        // 医疗机构填报人
        setlinfoUpld.setMedinsFillPsn(getDropdownBox.getName());
        // 医疗机构填报部门
        setlinfoUpld.setMedinsFillDept(getDropdownBox.getDeptName());
        // 离院方式 我们是从 0 开始的所以要加 1
        setlinfoUpld.setDscgWay(DecimalUtil.add1(setlinfoUpld.getDscgWay(), "1"));
        // 治疗类别 我们是从 0 开始的所以要加 1
        setlinfoUpld.setTrtType(DecimalUtil.add1(setlinfoUpld.getTrtType(), "10"));
        // 长沙总控的都传这个
        setlinfoUpld.setHsorg("长沙市医疗保障事务中心");
        setlinfoUpld.setHsorgOpter("长沙市医疗保障事务中心");
        // 因为我们是三级医院 所以就是三
        setlinfoUpld.setHiSetlLv("3");
        // 票据代码
        dealDzfp(patNo, times, ledgerSn);
        String billNo = dao.billNo(patNo, times, ledgerSn);
        if("00000000".equals(billNo)){
            billNo = "";
        }
        setlinfoUpld.setBillNo(billNo);
        setlinfoUpld.setBillCode("143001913350");
        setlinfoUpld.setBizSn(SnowFlakeId.instance().nextId());

        // 新生儿入院类型写死为1
        if (StringUtil.notBlank(setlinfoUpld.getNwbAge()) && NumberUtil.isNumber(setlinfoUpld.getNwbAge()) && Convert.toInt(setlinfoUpld.getNwbAge(), 0) > 0) {
            setlinfoUpld.setNwbAdmType("1");
        }
        String medType = dao.getMedicalCategory(patNo, times, ledgerSn);
        setlinfoUpld.setHiPaymtd(CommonUtil.calcHiPaymtd(setlinfoUpld.getInsuplc(), medType, setlinfoUpld.getHiType(), setlinfoUpld.getSetlEndDate()).toString());
        //  如果是 职工基本医疗保险的话 没有单位名称和地址 那么就 写死成 普通职工 和 现住址
        if ("310".equals(setlinfoUpld.getHiType())) {
            if (StringUtil.isBlank(setlinfoUpld.getEmpAddr())) {
                setlinfoUpld.setEmpAddr(setlinfoUpld.getCurrAddr());
            }
            if (StringUtil.isBlank(setlinfoUpld.getEmpName())) {
                setlinfoUpld.setEmpName("普通职工");
            }
            if (StringUtil.isBlank(setlinfoUpld.getEmpTel())) {
                setlinfoUpld.setEmpTel(setlinfoUpld.getConerTel());
            }
            if (StringUtil.isBlank(setlinfoUpld.getPoscode())) {
                setlinfoUpld.setPoscode("410000");
            }
        }
        //性别
        try {
            setlinfoUpld.setGend(IdcardUtil.getGenderByIdCard(setlinfoUpld.getCertno()) == 1 ? "1" : "2");
        } catch (Exception e) {

        }
        //出生日期
        try {
            if (Objects.equals(setlinfoUpld.getPatnCertType(), "01") && StringUtil.notBlank(setlinfoUpld.getCertno())) {
                String format = cn.hutool.core.date.DateUtil.format(IdcardUtil.getBirthDate(setlinfoUpld.getCertno()), "yyyy-MM-dd");
                setlinfoUpld.setBrdy(format);
                setlinfoUpld.setAge(Convert.toStr(cn.hutool.core.date.DateUtil.age(cn.hutool.core.date.DateUtil.parseDate(format), setlinfoUpld.getAdmTime())));
            }
        } catch (Exception e) {
            log.error("e", e);
        }
        //出院时间 中间断账没有出院 用结算时间
        if (dao.countZy(patNo, times) != null) {
            Map<String, Date> setTimeMap = dao.selelctSetlBeginAndEndTime(patNo, times, ledgerSn);
            setlinfoUpld.setAdmTime(setTimeMap.get("begntime"));
            setlinfoUpld.setDscgTime(setTimeMap.get("endtime"));
            long between = cn.hutool.core.date.DateUtil.betweenDay(setTimeMap.get("begntime"), setTimeMap.get("endtime"), true);
            setlinfoUpld.setActIptDays(Convert.toStr(between == 0 ? 1 : between));
        }
        setlinfoUpld.setPoscode(StringUtil.isBlank(setlinfoUpld.getPoscode()) ? "430000" : setlinfoUpld.getPoscode());

        //再31天再住院目的
        if ("-".equals(setlinfoUpld.getDaysRinpPup31())) {
            setlinfoUpld.setDaysRinpPup31("");
            setlinfoUpld.setDaysRinpFlag31("1");
        }
        // 呼吸机使用时长
        Integer ventUsedDura = dao.ventilatorUseTime(patNo, times);
        if (ventUsedDura != null) {
            setlinfoUpld.setVentUsedDura(secondsToTime(ventUsedDura));
        }

        // 医疗类别为 生育
        boolean isFertilitySign = isFertilitySign(patNo, times, ledgerSn);
        if (isFertilitySign) {
            // 生育类别不需要下面的这些
            setlinfoUpld.setNwbAge(null);
            setlinfoUpld.setNwbAdmType(null);
        }
        List<String> urbanAndRuralMedicalInsurance = Arrays.asList("390", "392");
        // 城乡医保类型可不填这两项
        if (urbanAndRuralMedicalInsurance.contains(setlinfoUpld.getHiType())) {
            setlinfoUpld.setEmpTel(null);
            setlinfoUpld.setPoscode(null);
        }
        //  颅脑损伤患者昏迷时间 没有就不填写
        if ("0/0/0".equals(setlinfoUpld.getPwcryAfadmComaDura())) {
            setlinfoUpld.setPwcryAfadmComaDura(null);
        }
        if ("0/0/0".equals(setlinfoUpld.getPwcryBfadmComaDura())) {
            setlinfoUpld.setPwcryBfadmComaDura(null);
        }
        setlinfoUpld.setSpPsnType(null);
        return setlinfoUpld;
    }

    private void dealDzfp(String patNo, Integer times, Integer ledgerSn) {
        try {
            PatientParam param = new PatientParam();
            param.setInpatientNo(patNo);
            param.setAdmissTimes(times);
            param.setLedgerSn(ledgerSn);
            param.setReceiptSn(1);
            param.setTypeFlag(3);
            param.setType("0");
            log.info("[dealDzfp]查询电子发票传参住院号={},次数={},账页号={}",patNo,times,ledgerSn);
            ResultVo<Map<String, Object>> mapResultVo = cashierProcessService.downDzInvoice(param);
            log.info("[dealDzfp]查询电子发票返回消息,{}",mapResultVo.getMessage());
        }catch (Exception e){
            log.error("[dealDzfp]结算单上传查询电子发票失败:",e);
        }

    }

    private SetlinfoUpld getSetlinfoUpld2(String patNo, Integer times) {
        if (dao.countZy(patNo, times) == null) {
            return dao.setlinfo2(patNo, times, ZyActpatient.ZY_INACTPATIENT);
        } else {
            return dao.setlinfo2(patNo, times, ZyActpatient.ZY_ACTPATIENT);
        }
    }

    /**
     * @description:是否质控通过
     * @author: lihong
     * @date: 2022/12/26 11:01
     * @param: patNo
     * @param: times
     * @return: thyyxxk.webserver.entity.ResultVo<java.util.Map < java.lang.String, java.lang.Object>>
     **/
    public ResultVo<Map<String, Object>> qualityPass(String patNo, Integer times) {
        Map<String, Object> map = new HashMap<>();
        map.put("qualityPassFlag", isQualityPass(patNo, times));
        return ResultVoUtil.success(map);
    }

    public boolean isQualityPass(String patNo, Integer times) {
        Integer auditFlag = dao.qualityPass(patNo, times);
        boolean flag = false;
        if (auditFlag != null && auditFlag == 1) {
            flag = true;
        }
        return flag;
    }

    /**
     * @description:是否是在院病人
     * @author: lihong
     * @date: 2022/12/26 16:16
     * @param: patNo
     * @param: times
     * @return: thyyxxk.webserver.entity.ResultVo<java.lang.Boolean>
     **/
    public ResultVo<Boolean> isInHospital(String patNo, Integer times) {
        Integer count = dao.isInHospital(patNo, times);
        boolean flag = false;
        if (count <= 0) {
            flag = true;
        }
        return ResultVoUtil.success(flag);
    }

    public ResultVo<SiSetlinfoTemp> getJieSuanDetail(String patNo, Integer times, Integer ledgerSn) {
        SiSetlinfoTemp jieSuanDetail = dao.countZy(patNo, times) == null ? dao.getJieSuanDetail(patNo, times, ledgerSn, ZyActpatient.ZY_INACTPATIENT) : dao.getJieSuanDetail(patNo, times, ledgerSn, ZyActpatient.ZY_ACTPATIENT);
        jieSuanDetail.setGendName("1".equals(jieSuanDetail.getGend()) ? "男" : "女");
        if (jieSuanDetail.getClrOptinsName() == null) {
            if ("439900".equals(jieSuanDetail.getClrOptins())) {
                jieSuanDetail.setClrOptinsName("省本级");
            } else if ("430199".equals(jieSuanDetail.getClrOptins())) {
                jieSuanDetail.setClrOptinsName("市本级");
            }
        }
        Insutype insutype = Insutype.get(jieSuanDetail.getInsutype());
        if (null != insutype) {
            jieSuanDetail.setInsutypeName(insutype.getName());
        }
        PsnType psnType = PsnType.get(jieSuanDetail.getPsnType());
        if (null != psnType) {
            jieSuanDetail.setPsnTypeName(psnType.getName());
        }
        MedType medType = MedType.get(jieSuanDetail.getMedType());
        if (null != medType) {
            jieSuanDetail.setMedTypeName(medType.getName());
        }


        return ResultVoUtil.success(jieSuanDetail);
    }

    /**
     * @description:申请撤回审核记录
     * @author: lihong
     * @date: 2022/12/28 11:22
     * @param: patNo
     * @param: times
     * @return: thyyxxk.webserver.entity.ResultVo<java.lang.Boolean>
     **/
    public ResultVo<String> shenQingCheHui(String patNo, Integer times) {
        TYbSetlModifyReq setlModifyReq = dao.getSetlModifyReq(patNo, times);
        if (setlModifyReq.getAuditFlag() != null
            && (setlModifyReq.getAuditFlag() == 1 || setlModifyReq.getAuditFlag() == 2)
        ) {
            String userId = TokenUtil.getInstance().getTokenUserId();
            if (userId.equals(setlModifyReq.getAuditStaff())) {
                //删除最近的审核历史记录
                dao.deletelatestSetlAuditLog(patNo, times);
                //将审核记录置空,还原为待审核状态
                dao.updateSetlModifyReq(patNo, times);
            } else {
                throw new BizException(ExceptionEnum.LOGICAL_ERROR, "当前最新的审核记录不是您,请不要操作撤销!");
            }
        } else {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "只有审核驳回或审核通过状态才能申请撤销审核操作");
        }
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "撤销成功");
    }

    /**
     * @description:查询审核信息
     * @author: lihong
     * @date: 2022/12/28 16:06
     * @param: patNo
     * @param: times
     * @return: thyyxxk.webserver.entity.ResultVo<java.lang.String>
     **/
    public ResultVo<TYbSetlModifyReq> querySetlModifyReq(String patNo, Integer times) {
        TYbSetlModifyReq setlModifyReq = dao.getSetlModifyReq(patNo, times);
        return ResultVoUtil.success(setlModifyReq);
    }

    /**
     * @description:查询上传日志 分页
     * @author: lihong
     * @date: 2023/1/4 14:28
     * @param: query
     **/
    public IPage<AutoUploadBill> queryUploadInfo(AutoUploadBill query) {
        return autoUploadBillService.queryPage(query);
    }

    /**
     * @description:病案检查
     * @author: lihong
     * @date: 2023/1/5 16:40
     * @param: param
     * @return: thyyxxk.webserver.entity.ResultVo<java.lang.String>
     **/
    public ResultVo<Map<String, List<CodeName>>> sheetVerification(ZyInactpatient param) {
        SheetOverview sheetOverview = new SheetOverview();
        sheetOverview.setBah(param.getInpatientNo());
        sheetOverview.setTimes(param.getAdmissTimes());
        sheetOverview.setInOutFlag(2);
        ResultVo<Map<String, List<CodeName>>> mapResultVo = caseFrontSheetMainService.sheetVerification(sheetOverview);
        return mapResultVo;
    }

    /**
     * @description:查询科室配置信息
     * @author: lihong
     * @date: 2023/1/9 15:46
     * @param: query
     * @return: java.lang.Object
     **/
    public List<String> querySetlDeptConfInfo(TSetlDeptConf query) {
        List<String> result = new ArrayList<>();
        List<TSetlDeptConf> tSetlDeptConfs = tSetlDeptConfService.querySetlDeptConfInfo(query);
        if (ListUtil.notBlank(tSetlDeptConfs)) {
            result = tSetlDeptConfs.stream().map(obj -> obj.getDeptCode()).collect(Collectors.toList());
        }
        return result;
    }

    /**
     * @description:保存科室配置数据
     * @author: lihong
     * @date: 2023/1/9 16:09
     * @param: data
     **/
    public void saveSetlDeptConfInfo(List<TSetlDeptConf> data) {
        AssertUtil.isnotBlank(data, "保存的数据不能为空");
        AssertUtil.isnotBlank(data.get(0).getCode(), "人员编码不能为空");
        QueryWrapper delWrapper = new QueryWrapper();
        delWrapper.eq("code", data.get(0).getCode());
        tSetlDeptConfService.remove(delWrapper);
        tSetlDeptConfService.batchSaveData(data);
    }

    public ResultVo<Integer> getUploadMaxDay() {
        String temp = dao.getDictValueByDictName("1.1", "1");
        Integer day = NumberUtil.isInteger(temp) ? Integer.parseInt(temp) : 7;
        return ResultVoUtil.success(day);
    }

    public IPage<TUploadDrgGroup> queryDrgGroupPage(TUploadDrgGroup query) {
        return tUploadDrgGroupService.queryUploadDrgGroupPage(query);
    }

    public void exportDrgGroupInfo(HttpServletResponse response, TUploadDrgGroup query) {
        tUploadDrgGroupService.exportDrgGroupInfo(response, query);
    }

    public ResultVo<String> updateBmyBz(SiSetlinfoTemp data) {
        if (StrUtil.isNotBlank(data.getBzUpdate()) && !data.getBzUpdate().equals(TokenUtil.getInstance().getTokenUserId())) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "只能[" + userCache.getEmployeeName(data.getBzUpdate()) + "]本人进行修改");
        }
        dao.updateBmyBz(data.getPatNo(), data.getTimes(), data.getLedgerSn(), data.getBmyBz(), TokenUtil.getInstance().getTokenUserId());
        return ResultVoUtil.success();
    }

    public ResultVo<String> validateYbCode(String code) {
        UserInfo userInfo = userCache.get(code);
        String str = "";
        if (userInfo == null || StringUtil.isBlank(userInfo.getYbCode())) {
            str = "[" + userInfo.getName() + "],医师医保编码不能为空,请找医保科维护该医师医保编码";
        } else if (!userInfo.getYbCode().startsWith("D")) {
            str = "[" + userInfo.getName() + "],医师医保编码首字母应以D开头,该人员可能不是医师,请选择正确的医师,或者医师医保编码维护错误,请找医保科维护该医生医保编码";
        }
        return ResultVoUtil.success(str);

    }

    public ResultVo<String> delAuditLog(TYbSetlModifyReq param) {
        TYbSetlModifyReq setlModifyReq = dao.getSetlModifyReq(param.getPatNo(), param.getTimes());
        if (setlModifyReq == null) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "已经是未审核状态,不能删除审核记录");
        } else {
            UserInfo userInfo = userCache.getUserInfoByToken();
            dao.insertDisYbModifyDel(param.getPatNo(), param.getTimes());
            dao.insOprtModifiyDel(param.getPatNo(), param.getTimes());
            dao.insertAuditLogsDel(param.getPatNo(), param.getTimes(), userInfo.getCode(), userInfo.getName());
            dao.delAuditLog(param.getPatNo(), param.getTimes());
        }
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "删除成功");
    }
}
