package thyyxxk.webserver.service.inpatient;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import thyyxxk.webserver.config.exception.BizException;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.constants.Capacity;
import thyyxxk.webserver.constants.sidicts.MedType;
import thyyxxk.webserver.constants.sidicts.PsnCertType;
import thyyxxk.webserver.dao.his.inpatient.DismissDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.inpatient.dismiss.ActOrderDetail;
import thyyxxk.webserver.entity.inpatient.dismiss.ActOrderGroup;
import thyyxxk.webserver.entity.inpatient.dismiss.BriefMdtrtInfo;
import thyyxxk.webserver.entity.inpatient.dismiss.DepositFile;
import thyyxxk.webserver.entity.inpatient.dismiss.IllegalFee;
import thyyxxk.webserver.entity.inpatient.dismiss.MedinsSettleFee;
import thyyxxk.webserver.entity.inpatient.dismiss.ReceiptEntity;
import thyyxxk.webserver.entity.inpatient.dismiss.ReceiptFee;
import thyyxxk.webserver.entity.inpatient.patient.Overview;
import thyyxxk.webserver.entity.inpatient.patient.Patient;
import thyyxxk.webserver.entity.medicalinsurance.injury.InjuryCareQualification;
import thyyxxk.webserver.http.drg.DrgWebApi;
import thyyxxk.webserver.service.externalhttp.SiInjuryFeeUpld;
import thyyxxk.webserver.service.externalhttp.SiZySrvc;
import thyyxxk.webserver.service.inpatient.charge.CashierProcessService;
import thyyxxk.webserver.utils.DateUtil;
import thyyxxk.webserver.utils.DecimalUtil;
import thyyxxk.webserver.utils.IdCardUtil;
import thyyxxk.webserver.utils.ListUtil;
import thyyxxk.webserver.utils.ResultVoUtil;
import thyyxxk.webserver.utils.StringUtil;
import thyyxxk.webserver.utils.TokenUtil;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author dj
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DismissService {
    private final DismissDao dao;
    private final SiZySrvc zySrvc;
    private final SiInjuryFeeUpld injuryFeeUpld;
    private final CashierProcessService cashierService;
    private final RestTemplate template;
    private final DrgWebApi drgWebApi;

    @Value("${si-zy-fee-url}")
    private String siZyFeeUrl;
    @Value("${si-injury-fee-url}")
    private String siInjuryFeeUrl;
    @Value("${rmHkUserApi}")
    private String rmHkUserApi;


    public ResultVo<JSONArray> powersiPreDischarge(String visitId) {
        return drgWebApi.powersiPreDischarge(visitId);
    }

    public ResultVo<Object> dismiss(Patient param) {
        ResultVo<List<ActOrderGroup>> actOrders = getActOrders(param.getInpatientNo(), param.getAdmissTimes());
        if (!Objects.equals(actOrders.getCode(), ExceptionEnum.SUCCESS.getCode())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, actOrders.getMessage());
        }
        if (!actOrders.getData().isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.ABNORMAL_YZ_ACT_ORDER, actOrders.getData());
        }
        ResultVo<List<IllegalFee>> calculate = calculateForDismiss(param);
        if (Objects.equals(calculate.getCode(), ExceptionEnum.EXIST_NEGATIVE_FEES.getCode())) {
            return ResultVoUtil.fail(ExceptionEnum.EXIST_NEGATIVE_FEES, calculate.getData());
        }
        if (!Objects.equals(calculate.getCode(), ExceptionEnum.SUCCESS.getCode())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, calculate.getMessage());
        }
        return ResultVoUtil.success();
    }

    public ResultVo<List<ActOrderGroup>> getActOrders(String patNo, Integer times) {
        final Integer ledgerSn = dao.getLedgerSn(patNo, times);
        if (ledgerSn < 1) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "获取帐页数失败。");
        }
        dao.acceptFeeStepOne(patNo, times);
        if (dao.acceptFeeStepTwo(patNo, times) < 0) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "接收费用失败。");
        }
        if (dao.getOrderList(patNo, times) < 0) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "查询医嘱失败。");
        }
        List<ActOrderDetail> allOrders = dao.getActOrderDetail();
        if (allOrders == null) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "查询医嘱失败。");
        }
        return analyzeActOrders(allOrders);
    }

    private ResultVo<List<ActOrderGroup>> analyzeActOrders(List<ActOrderDetail> allOrders) {
        HashMap<String, ActOrderGroup> temp = new HashMap<>(Capacity.DEFAULT);
        for (ActOrderDetail item : allOrders) {
            String actOrderNo = item.getActOrderNo();
            String fee = item.getChargeFee();
            if (!temp.containsKey(actOrderNo)) {
                ActOrderGroup aModel = new ActOrderGroup(actOrderNo, fee, item.getChargeStatus(), item.getCxFlag());
                if (aModel.getList() == null) {
                    aModel.setList(new ArrayList<>());
                }
                aModel.getList().add(item);
                temp.put(actOrderNo, aModel);
            } else {
                temp.get(actOrderNo).setFee(DecimalUtil.add(fee, temp.get(actOrderNo).getFee()));
                temp.get(actOrderNo).getList().add(item);
            }
        }
        List<ActOrderGroup> list = new ArrayList<>();
        for (HashMap.Entry<String, ActOrderGroup> modelEntry : temp.entrySet()) {
            list.add(modelEntry.getValue());
        }
        return ResultVoUtil.success(list);
    }

    public ResultVo<List<IllegalFee>> calculateForDismiss(Patient param) {
        final String patNo = param.getInpatientNo();
        final Integer times = param.getAdmissTimes();
        if (!param.getMidSetl()) {
            Integer disActOrderCount = dao.countDisActOrders(patNo, times);
            if (null == disActOrderCount || disActOrderCount == 0) {
                disActOrderCount = dao.countDisActOrders2(patNo, times);
                if (null == disActOrderCount) {
                    disActOrderCount = 0;
                }
            }
            if (disActOrderCount < 1) {
                throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者没有出院医嘱，请检查。");
            }
            if (disActOrderCount > 1) {
                throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者的出院医嘱不止一条，请检查。");
            }
        }
        if (StringUtil.isBlank(param.getDutyNurse())) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "患者责任护士不能为空，请前往入院登记页面填写并保存。");
        }
        if (StringUtil.isBlank(param.getCountry())) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "患者国籍不能为空，请前往入院登记页面填写并保存。");
        }
        if (StringUtil.isBlank(param.getNation())) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "患者民族不能为空，请前往入院登记页面填写并保存。");
        }
        if (StringUtil.isBlank(param.getContactName())) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "患者联系人不能为空，请前往入院登记页面填写并保存。");
        }
        if (StringUtil.isBlank(param.getContactRelation())) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "患者联系人关系不能为空，请前往入院登记页面填写并保存。");
        }
        if (StringUtil.isBlank(param.getContactAddrName())) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "患者联系人地址不能为空，请前往入院登记页面填写并保存。");
        }
        if (StringUtil.isBlank(param.getContactPhone())) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "患者联系人电话不能为空，请前往入院登记页面填写并保存。");
        }
        if (null == param.getAdmissDate()) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "没有找到入院时间，请重新获取病人信息。");
        }
        if (StringUtil.isBlank(param.getPsnCertType())) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "患者证件类型不能为空，请前往入院登记页面补充并保存。");
        }
        if (param.getPsnCertType().equals(PsnCertType.RESIDENT_IDENTITY_CARD.getCode()) &&
            !IdCardUtil.isValidatedIdCard(param.getSocialNo())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "身份证不合法！");
        }
        Integer age = param.getAge();
        if (param.getPsnCertType().equals(PsnCertType.RESIDENT_IDENTITY_CARD.getCode())) {
            age = IdCardUtil.getAgeByIdCard(param.getSocialNo());
        }
        if (null != age && (age < 16 || age > 60)) {
            if (param.getName().equals(param.getContactName()) ||
                param.getContactRelation().equals("0")) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "16岁以下或60岁以上的患者，联系人不能填写本人。");
            }
        }
        Date endtime = getEndtime(param.getMidSetl(), patNo, times, param.getZjdzDatetime());
        Date tmpendtime = param.getMidSetl() ? endtime : DateUtil.parse("2999-12-31 23:59:59");
        final int ledgerSn = dao.getLedgerSn(patNo, times);
        if (dao.hasUnsettledStepOne(patNo, times, ledgerSn) < 0) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "获取记账信息失败。");
        }
        if (dao.hasUnsettledStepTwo(patNo, times) > 0) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者有未结算的记账金额，请联系收费窗口。");
        }
        if (dao.hasNotAccounted(patNo, times) > 0) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者有未上账金额。");
        }
        List<String> unreceivedDrug = dao.hasUnreceivedDrugList(patNo, times);
        if (ListUtil.notBlank(unreceivedDrug)) {
            throw new BizException(ExceptionEnum.LOGICAL_HTML_ERROR, dischargeErrorMessage(unreceivedDrug));
        }
        if (dao.hasUnreceivedFees(patNo, times, tmpendtime) > 0) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者有未接收的费用，请联系医技科室确认或取消。");
        }
        if (dao.hasUnSubmitDrugList(patNo, times) > 0) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者有未提交的药单。");
        }
        if (dao.hasUnDeliverHerbal(patNo, times) > 0) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者有未发药的中草药/颗粒剂。");
        }
        List<IllegalFee> unhandledList = dao.hasUntreatedDrugOrder(patNo, times);
        if (!unhandledList.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.EXIST_UNHANDLED_DRUG_ORDER, unhandledList);
        }
        List<IllegalFee> refundDrugs = dao.selectPageNoTys(patNo, times);
        if (!refundDrugs.isEmpty()) {
            for (IllegalFee drug : refundDrugs) {
                if (Objects.equals(drug.getPageNoTy(),"-1")) {
                    drug.setPageNoTy("未提交");
                    drug.setRemark(StrUtil.format("有【{}】,退药单未生成，请去入院登记的【生成退药单】中生成退药单。",
                            DateUtil.formatDatetime(drug.getYpChargeDate(), "yyyy-MM-dd HH:mm")));
                } else {
                    drug.setRemark("请联系药房处理，如果需要退费请药房点击同意，不需要退费请点击拒绝。");
                }
            }
            return ResultVoUtil.fail(ExceptionEnum.EXIST_UNHANDLED_REFUND_DRUG, refundDrugs);
        }
        if (dao.hasUnconfirmedMedicalTech(patNo, times, tmpendtime) > 0) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者有未确认的医技。");
        }
        List<IllegalFee> feeNegativeList = dao.feeOrderNegative(patNo, times);
        if (!feeNegativeList.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.EXIST_NEGATIVE_FEES, feeNegativeList);
        }
        if (dao.hasSettled(patNo, times, ledgerSn) != 0) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者已存在结算信息。");
        }
        if (dao.hasUncheckedFee(patNo, times, ledgerSn) > 0) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者有未结账的费用。");
        }
        Date begntime = getBegntime(patNo, times, ledgerSn, "zy_actpatient");
        dismissFeeAnalyse(patNo, times, ledgerSn, begntime, tmpendtime);

        BigDecimal feeOffset = dao.getFeeOffset(patNo, times, ledgerSn);
        if (feeOffset.compareTo(BigDecimal.ZERO) != 0) {
            BigDecimal beforeAdmFee = dao.selectOverTimeLimitFee(patNo, times, ledgerSn, "<=", begntime);
            if (beforeAdmFee.compareTo(BigDecimal.ZERO) != 0) {
                throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者明细费用与账页费用不一致，有【" + beforeAdmFee + "元】小于入院时间的费用。");
            }
            if (!param.getMidSetl()) {
                BigDecimal afterDisFee = dao.selectOverTimeLimitFee(patNo, times, ledgerSn, ">", tmpendtime);
                if (afterDisFee.compareTo(BigDecimal.ZERO) != 0) {
                    throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者明细费用与账页费用不一致，有【" + afterDisFee + "元】大于出院时间的费用。");
                }
                throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者明细费用与账页费用不一致，请确认所有医嘱、药单等都已接收。");
            }
        }

        if (dao.selectReceiptCount(patNo, times, ledgerSn) > 0) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者有未冲销的发票，请联系财务进行冲销。");
        }

        dao.deleteTemporaryTable(patNo, times);
        BriefMdtrtInfo medinfo = dao.selectMdtrtId(patNo, times, ledgerSn);
        if (null == medinfo) {
            medinfo = new BriefMdtrtInfo();
        }
        if (StringUtil.notBlank(medinfo.getMdtrtId())) {
            if (dao.hasDismissDiag(patNo, times) == 0) {
                throw new BizException(ExceptionEnum.LOGICAL_ERROR, "此患者没有医保出院诊断。");
            }
            if (null != param.getDeathFlag() && param.getDeathFlag()) {
                return ResultVoUtil.success();
            }
            Integer deathOrderCount = dao.selectDeathOrderCount(patNo, times);
            if (null != deathOrderCount && deathOrderCount > 0) {
                return ResultVoUtil.success();
            }
            Overview o = new Overview();
            o.setInpatientNo(patNo);
            o.setAdmissTimes(times);
            o.setLedgerSn(ledgerSn);
            o.setStaffId(param.getStaffId());
            o.setSid(param.getSid());
            o.setMidSetl(param.getMidSetl());
            if (o.getMidSetl()) {
                o.setBegntime(begntime);
                o.setEndtime(tmpendtime);
            }
            ResultVo<String> feeCheck = zySrvc.uploadFeeDetail(siZyFeeUrl, o);
            if (!Objects.equals(feeCheck.getCode(), ExceptionEnum.SUCCESS.getCode())) {
                throw new BizException(ExceptionEnum.LOGICAL_ERROR, feeCheck.getMessage());
            }
        }
        return ResultVoUtil.success();
    }

    private String dischargeErrorMessage(List<String> messages) {
        StringBuilder str = new StringBuilder("此患者有未接收的药单" + "<br />");
        for (String message : messages) {
            str.append(message).append("<br>");
        }
        return str.toString();
    }

    @Transactional(rollbackFor = Exception.class)
    public String executeDischarging(MedinsSettleFee settleFee) throws BizException {
        updateHicNo(settleFee.getInpatientNo());
        settleFee.setLedgerSn(dao.getLedgerSn(settleFee.getInpatientNo(), settleFee.getAdmissTimes()));
        BriefMdtrtInfo medinfo = dao.selectMdtrtId(settleFee.getInpatientNo(), settleFee.getAdmissTimes(), settleFee.getLedgerSn());
        if (null == medinfo) {
            medinfo = new BriefMdtrtInfo();
        }
        // 医保病人进行医保结算
        if (StringUtil.notBlank(medinfo.getMdtrtId())) {
            dao.deleteZyLedgerFileYb(settleFee.getInpatientNo(), settleFee.getAdmissTimes(), settleFee.getLedgerSn());
            // 如果医院支付为正，则 现金支付 = 现金支付 + 医院支付
            if (!settleFee.getHospitalPay().startsWith("-")) {
                settleFee.setXjzf(DecimalUtil.add(settleFee.getXjzf(), settleFee.getHospitalPay()));
            }
            if (dao.insertZyLedgerFileYb(settleFee) < 1) {
                throw new BizException(ExceptionEnum.LOGICAL_ERROR, "写医保结算表失败。");
            }
        }
        if (writeReceiptTable(settleFee) < 1) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "写发票表失败。");
        }
        if (updateCostStatusToSettled(settleFee, StringUtil.notBlank(medinfo.getMdtrtId())) < 1) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "更新费用状态失败。");
        }
        int code = settleFee.getMidSetl() ? hisMiddleSettle(settleFee) : setHisStatusOut(settleFee);
        if (code < 1) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "更新住院状态失败。" + code);
        }
        new DestructionUser(settleFee.getInpatientNo(), settleFee.getAdmissTimes()).start();
        return "OK";
    }

    class DestructionUser extends Thread {
        private final String patNo;
        private final Integer times;

        public DestructionUser(String patNo, Integer times) {
            this.patNo = patNo;
            this.times = times;
        }

        @Override
        public void run() {
            try {
                JSONObject obj = new JSONObject();
                obj.put("patNo", patNo);
                obj.put("times", times);
                String res = template.postForObject(rmHkUserApi, obj, String.class);
                log.info("删除门禁。{}", res);
            } catch (Exception e) {
                log.error("删除患者门禁出错", e);
            }
        }
    }

    private int writeReceiptTable(MedinsSettleFee indata) {
        if (dao.beforeWriteReceiptTable(indata.getInpatientNo(), indata.getAdmissTimes(),
                indata.getLedgerSn()) < 1) {
            return -1;
        }
        Date admissDate = getBegntime(indata.getInpatientNo(), indata.getAdmissTimes(), indata.getLedgerSn(), indata.getTable());
        Date dismissDate = getEndtime(indata.getMidSetl(), indata.getInpatientNo(), indata.getAdmissTimes(),
                indata.getZjdzDatetime());
        Date tempendtime = indata.getMidSetl() ? dismissDate : DateUtil.parse("2999-12-31 23:59:59");
        ReceiptEntity receiptEntity = dismissFeeAnalyse(indata.getInpatientNo(), indata.getAdmissTimes(),
                indata.getLedgerSn(), admissDate, tempendtime);
        if (indata.getLedgerSn() > 1) {
            admissDate = DateUtil.addOneSecond(admissDate);
        }
        if (dao.writeReceiptTable(indata.getInpatientNo(), indata.getAdmissTimes(), indata.getLedgerSn(), 1,
                admissDate, dismissDate, indata.getWardCode(), indata.getDeptCode(), dismissDate, "01",
                indata.getStaffId(), receiptEntity.getAdult()) < 1) {
            return -1;
        }
        if (null != receiptEntity.getInfant()) {
            return dao.writeReceiptTable(indata.getInpatientNo(), indata.getAdmissTimes(), indata.getLedgerSn(), 4,
                    admissDate, dismissDate, indata.getWardCode(), indata.getDeptCode(), dismissDate, "04",
                    indata.getStaffId(), receiptEntity.getInfant());
        }
        return 1;
    }

    private ReceiptEntity dismissFeeAnalyse(String patNo, int times, int ledgerSn, Date begntime, Date endtime) {
        Map<String, String> ledgerMap = initReceiptMap();
        Map<String, String> infantMap = initReceiptMap();
        Map<String, String> adultMap = initReceiptMap();
        List<ReceiptFee> ledgerFees = dao.selectLedgerFees(patNo, times, ledgerSn, begntime, endtime);
        if (null == ledgerFees) {
            ledgerFees = new ArrayList<>();
        }
        for (ReceiptFee fee : ledgerFees) {
            ledgerMap.replace(fee.getBillCode(), fee.getLedgerFee());
            ledgerMap.replace("total", DecimalUtil.add(ledgerMap.get("total"), fee.getLedgerFee()));

            infantMap.replace(fee.getBillCode(), fee.getInfantFee());
            infantMap.replace("total", DecimalUtil.add(infantMap.get("total"), fee.getInfantFee()));

            adultMap.replace(fee.getBillCode(), fee.getAdultFee());
            adultMap.replace("total", DecimalUtil.add(adultMap.get("total"), fee.getAdultFee()));

        }
        String restype = dao.selectResponceType(patNo);
        String deposit = dao.selectDepositSumamt(patNo, times, ledgerSn);
        if (StringUtil.isBlank(deposit)) {
            deposit = "0";
        }
        String balance = DecimalUtil.minus(deposit, ledgerMap.get("total"));
        dao.updateZyLedgerFileCharges(patNo, times, ledgerSn, deposit, balance, restype, ledgerMap);
        ReceiptEntity entity = new ReceiptEntity();
        if (DecimalUtil.compare(infantMap.get("total"), "0") == 1) {
            String patNo1 = patNo + "$1";
            String patNo6 = patNo + "$6";
            dao.updateInfantfee(patNo1, patNo6, times, infantMap);
            entity.setInfant(infantMap);
        }
        String totalCost = dao.selectTotalCharge(patNo, times);
        dao.updateZyActpatientCharges(patNo, totalCost, balance, ledgerMap);
        entity.setAdult(adultMap);
        return entity;
    }

    private Map<String, String> initReceiptMap() {
        Map<String, String> map = new HashMap<>();
        map.put("total", "0.00");
        List<String> billCodes = dao.selectBillCodes();
        billCodes.forEach(itm -> map.put(itm, "0.00"));
        return map;
    }

    public Date getBegntime(String patNo, int times, int ledgerSn, String table) {
        return ledgerSn > 1 ? dao.selectLastLedgerAccountDate(patNo, times, ledgerSn) :
                dao.selectAdmissDate(patNo, times, table);
    }

    private Date getEndtime(Boolean midsetl, String patNo, Integer times, Date zjdzDate) {
        if (midsetl) {
            return zjdzDate;
        }
        Date disdate = dao.selectActOrderDisDate(patNo, times);
        if (null == disdate) {
            disdate = dao.selectActOrderDisDate2(patNo, times);
        }
        return disdate;
    }

    private int updateCostStatusToSettled(MedinsSettleFee settle, boolean medins) {
        dao.updateZyDetailCharge(settle.getInpatientNo(), settle.getAdmissTimes(), settle.getLedgerSn());
        if (!settle.getMidSetl()) {
            settle.setZjdzDatetime(new Date());
        }
        if (medins) {
            int hasInfant = dao.hasInfant(settle.getInpatientNo(), settle.getAdmissTimes());
            if (hasInfant == 0) {
                return dao.updateCostStatusWithoutInfant(settle);
            }
            return dao.updateCostStatusWithInfant(settle);
        }
        return dao.updateZifeiCostStatus(settle);
    }

    private int setHisStatusOut(MedinsSettleFee settle) {
        final Date disDate;
        String patNo = settle.getInpatientNo();
        int times = settle.getAdmissTimes();
        if ("zy_actpatient".equals(settle.getTable())) {
            disDate = dao.selectActOrderDisDate(patNo, times);
        } else {
            disDate = dao.selectActOrderDisDate2(patNo, times);
        }
        if (dao.updateZyActpatient(patNo, times,
                disDate, settle.getStaffId(), settle.getTable()) < 1) {
            return -1;
        }
        if ("zy_actpatient".equals(settle.getTable())) {
            dao.deleteZyInactpatient(patNo, times);
            if (dao.insertZyInactpatient(patNo, times) < 1) {
                return -2;
            }
        }
        final String patNo1 = patNo + "$1";
        final String patNo6 = patNo + "$6";
        dao.updateZyActpatientAgain(patNo1, patNo6, times, disDate, settle.getTable());
        if ("zy_actpatient".equals(settle.getTable())) {
            dao.insertZyInactpatientAgain(patNo1, patNo6, times);
        }
        if (dao.updateZyAdt(patNo, times, settle.getWardCode(), settle.getDeptCode(),
                settle.getBedNo(), disDate) < 1) {
            return -3;
        }
        dao.updateZyBedMi(patNo, times);
        dao.deleteZyActpatient(patNo);
        dao.deleteZyActpatientAgain(patNo1, patNo6, times);
        dao.deleteZjdzSettleDeposit(patNo, times);
        return insertNewZyWorkLog(settle);
    }

    private int insertNewZyWorkLog(MedinsSettleFee param) {
        final String userName = dao.getOperateName(param.getStaffId());
        String logType = param.getMidSetl() ? "zjdz" : "cyjs";
        return dao.insertNewZyWorkLog(param.getInpatientNo(), param.getAdmissTimes(), param.getLedgerSn(),
                param.getWardCode(), logType, param.getDeptCode(), param.getStaffId(), userName);
    }

    private int hisMiddleSettle(MedinsSettleFee param) {
        String patNo = param.getInpatientNo();
        int times = param.getAdmissTimes();
        Date onMoreSecond = DateUtil.addOneSecond(param.getZjdzDatetime());
        dao.clearMedinsInfo(patNo, times, onMoreSecond);

        int currentLedgerSn = dao.getLedgerSn(patNo, times);
        param.setLedgerSn(currentLedgerSn);
        int newLedgerSn = currentLedgerSn + 1;

        dao.updateTimesBilledByIncreaseOne(patNo, times, param.getTable());
        dao.insertNewLedgerFile(patNo, times, newLedgerSn);
        dao.updateFeesLedgerSn(patNo, times, newLedgerSn, currentLedgerSn, param.getZjdzDatetime());
        dao.updateZyLedgerFileTotalCharge(patNo, times, currentLedgerSn);
        dao.updateZyLedgerFileTotalCharge(patNo, times, newLedgerSn);

        DepositFile depositFile = dao.selectLatestDepositFile(patNo, times);
        if (null == depositFile) {
            return insertNewZyWorkLog(param);
        }
        String lastSettleAmount = dao.selectLastLedgerSettle(patNo, times, currentLedgerSn);
        if (StringUtil.isBlank(lastSettleAmount)) {
            return insertNewZyWorkLog(param);
        }
        BigDecimal settleDecimal = new BigDecimal(lastSettleAmount);
        if (settleDecimal.compareTo(BigDecimal.ZERO) < 1) {
            return insertNewZyWorkLog(param);
        }
        depositFile.setLedgerSn(newLedgerSn);
        depositFile.initZjdzSettleDeposit(lastSettleAmount);
        dao.insertNewDeposit(depositFile);
        return insertNewZyWorkLog(param);
    }

    private void updateHicNo(String zyh) {
        String hicNoNew = dao.getHicNoNew(zyh);
        if (null != hicNoNew) {
            if (hicNoNew.length() > 16) {
                hicNoNew = hicNoNew.substring(0, 16);
            }
            dao.updateCpy(zyh, hicNoNew);
            if (hicNoNew.length() > 10) {
                hicNoNew = hicNoNew.substring(0, 10);
            }
            dao.updateHic(zyh, hicNoNew);
        }
    }

}
