package thyyxxk.webserver.service.inpatient;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
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.Capacity;
import thyyxxk.webserver.constants.sidicts.MedType;
import thyyxxk.webserver.constants.sidicts.PsnCertType;
import thyyxxk.webserver.dao.his.inpatient.PatientDao;
import thyyxxk.webserver.dao.his.inpatient.Routines;
import thyyxxk.webserver.dao.his.zhuyuanyisheng.YiZhuLuRuDao;
import thyyxxk.webserver.entity.ResultVo;
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.dismiss.ZyDisYbDiag;
import thyyxxk.webserver.entity.inpatient.patient.*;
import thyyxxk.webserver.entity.zhuyuanyisheng.yizhuluru.HuanZheFeiYong;
import thyyxxk.webserver.entity.zhuyuanyisheng.yizhuluru.XinZhenYiZhu;
import thyyxxk.webserver.http.drg.DrgWebApi;
import thyyxxk.webserver.service.hutoolcache.UserCache;
import thyyxxk.webserver.service.zhuyuanyisheng.emr.EmrServer;
import thyyxxk.webserver.utils.*;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author dj
 */
@Slf4j
@Service
public class PatientService {
    private static final String ZD_MEDCN = "yp_zd_dict";
    private final PatientDao dao;
    private final Routines routines;
    private final YiZhuLuRuDao yiZhuLuRuDao;
    private final EmrServer emrServer;
    private final DrgWebApi drgWebApi;
    private final UserCache userCache;


    @Autowired
    public PatientService(PatientDao dao, Routines routines, YiZhuLuRuDao yiZhuLuRuDao, EmrServer emrServer, DrgWebApi drgWebApi, UserCache userCache) {
        this.dao = dao;
        this.routines = routines;
        this.yiZhuLuRuDao = yiZhuLuRuDao;
        this.emrServer = emrServer;
        this.drgWebApi = drgWebApi;
        this.userCache = userCache;
    }

    public ResultVo<List<Overview>> getOverView(String ward, Boolean viewBabies) {
        ward = "%" + ward + "%";
        String sql = "";
        if (!viewBabies) {
            sql = "and charindex('$',a.inpatient_no)=0 ";
        }
        return ResultVoUtil.success(dao.getOverView(ward, TokenUtil.getInstance().getTokenUserId(), sql));
    }

    public ResultVo<Patient> getPatientInfo(String inpatientNo) {
        Patient data = dao.getPatientInfo(inpatientNo, "zy_actpatient", 0);
        if (null == data) {
            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "没有住院号【" + inpatientNo + "】的在院业务！");
        }
        // 新增：查医保参保地行政区划
        Integer ledgerSn = data.getLedgerSn() != null ? data.getLedgerSn() : 0;
        String insuplcAdmdvs = dao.selectInsuplcAdmdvs(data.getInpatientNo(), data.getAdmissTimes(), ledgerSn);
        data.setInsuplcAdmdvs(insuplcAdmdvs);
        // 新增：查取消入院登记次数
        String canceAdmissCount = dao.selectCanceAdmissCount(data.getInpatientNo(), data.getAdmissTimes(), ledgerSn);
        data.setCanceAdmissCount(canceAdmissCount);
        if (null != data.getAdmdvs()) {
            Integer parentRegion = dao.selectParentRegion(data.getAdmdvs());
            if (null != parentRegion) {
                if (parentRegion == 100000) {
                    parentRegion = data.getAdmdvs();
                }
                data.setAdmdvsCascader(new Integer[]{parentRegion, data.getAdmdvs()});
            }
        }
        setExpenseInformation(data);
        return ResultVoUtil.success(data);
    }

    public ResultVo<Patient> getDisPatient(String inpatientNo, Integer times) {
        Patient data = dao.getPatientInfo(inpatientNo, "zy_inactpatient", times);
        if (null == data) {
            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "没有住院号【" + inpatientNo + "】的出院业务！");
        }
        setExpenseInformation(data);
        return ResultVoUtil.success(data);
    }

    public ResultVo<Patient> getPatientAll(String inpatientNo, Integer times) {
        Patient data = dao.getPatientInfo(inpatientNo, "view_zy_patient_all", times);
        if (null == data) {
            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "没有住院号【" + inpatientNo + "】住院业务！");
        }
        setExpenseInformation(data);
        return ResultVoUtil.success(data);
    }

    public Patient getPatientBaseInfo(String inpatientNo, Integer times, String inOutStatusFlag) {
        Patient data = dao.getPatientInfo(inpatientNo, "1".equals(inOutStatusFlag) ? "zy_inactpatient" : "zy_actpatient", times);
        String msg = "1".equals(inOutStatusFlag) ? "出院" : "在院";
        if (null == data) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "没有住院号【" + inpatientNo + "】的" + msg + "业务！");
        }
        setExpenseInformation(data);
        return data;
    }

    public ResultVo<JSONObject> getDrgPatInfo(Patient p) {
        BaseInfo bf = new BaseInfo();
        bf.setVisitId(p.getInpatientNo() + "_" + p.getAdmissTimes() + "_" + p.getLedgerSn())
                .setGend(p.getSex().toString())
                .setBrdy(p.getBirthDate())
                .setAge(p.getAge().toString())
                .setNwbAge("")
                .setNwbBirWt("")
                .setNwbAdmWt("")
                .setAdmTime(p.getAdmissDate())
                .setActIptDays(String.valueOf(DateUtil.daysBetween(new Date(), p.getAdmissDate())))
                .setTotalFee(p.getTotalCharge())
                .setCdntnPay("")
                .setIllPay("");
        JSONObject upload = new JSONObject();
        upload.put("base_info", bf);
        upload.put("dise_info_list", setDrgDisList(p));
        upload.put("oprt_info_list", setOprtInfoList(p));

        JSONObject res = drgWebApi.getDrgCaseQualityControlGroup(upload);
        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);
                    return ResultVoUtil.success(item);
                }
            }
        }
        return ResultVoUtil.success();
    }


    private List<DiseInfoList> setDrgDisList(Patient p) {
        List<DiseInfoList> list = new ArrayList<>();
        JSONObject emrJs = emrServer.getEmrPatientData(p.getInpatientNo(), p.getAdmissTimes());
        String id = p.getInpatientNo() + "_" + p.getAdmissTimes() + "_" + p.getLedgerSn();
        try {
            JSONArray disList = emrJs.getJSONArray("入院诊断");
            for (int i = 0; i < disList.size(); i++) {
                DiseInfoList temp = new DiseInfoList();
                JSONObject item = disList.getJSONObject(i);
                try {
                    temp.setVisitId(id)
                            .setDiagCode(item.getString("code"))
                            .setDiagName(item.getString("name"))
                            .setMaindiagFlag(i == 0 ? "1" : "0")
                            .setSortNo(String.valueOf(i + 1));
                    list.add(temp);
                } catch (Exception ignored) {
                }
            }
        } catch (Exception ignored) {
        }
        return list;
    }

    private List<OprtInfoList> setOprtInfoList(Patient p) {
        String id = p.getInpatientNo() + "_" + p.getAdmissTimes() + "_" + p.getLedgerSn();
        List<OprtInfoList> list = new ArrayList<>();
        JSONArray emrList = emrServer.getPatientSurgery(p.getInpatientNo(), p.getAdmissTimes());
        for (int i = 0; i < emrList.size(); i++) {
            JSONObject item = emrList.getJSONObject(i);
            JSONObject oprtName;
            try {
                oprtName = item.getJSONObject("手术名称");
            } catch (Exception e) {
                continue;
            }
            if (oprtName == null) {
                continue;
            }
            JSONArray oprtNameVals = null;
            try {
                oprtNameVals = oprtName.getJSONArray("value");
            } catch (Exception ignored) {
            }

            if (null == oprtNameVals) {
                continue;
            }
            for (int j = 0; j < oprtNameVals.size(); j++) {
                JSONObject opList = oprtNameVals.getJSONObject(j);
                OprtInfoList op = new OprtInfoList();
                op.setVisitId(id)
                        .setOprnOprtType((i + j) == 0 ? "1" : "2")
                        .setOprnOprtCode(opList.getString("code"))
                        .setOprnOprtName(opList.getString("name"))
                        .setSortNo(String.valueOf((i + j) + 1));
                list.add(op);
            }

        }
        return list;
    }


    /**
     * 设置患者费用信息
     *
     * @param data 患者数据
     */
    private void setExpenseInformation(@NotNull Patient data) {
        data.setMedTypeName(MedType.getName(data.getMedType()));
        data.setDutyNurseName(userCache.getEmployeeName(data.getDutyNurse()));

        HuanZheFeiYong feiYongZhanBi = yiZhuLuRuDao.feiYongXinXi(data.getInpatientNo(), data.getAdmissTimes(), data.getLedgerSn());
        if (feiYongZhanBi != null) {
            // 余额
            data.setBalance(feiYongZhanBi.getBalance());
            // 总费用
            data.setTotalCharge(feiYongZhanBi.getTotalCharge());
            // 药品 百分比
            data.setYp(DecimalUtil.getPercent(Double.parseDouble(feiYongZhanBi.getYp()), Double.parseDouble(feiYongZhanBi.getTotalCharge())));
            // 检验检查 百分比
            data.setJyjc(DecimalUtil.getPercent(Double.parseDouble(feiYongZhanBi.getJyjc()), Double.parseDouble(feiYongZhanBi.getTotalCharge())));
            // 医保 费用
            data.setChargeYb(feiYongZhanBi.getChargeYb());
            // 医保百分比
            data.setYb(DecimalUtil.getPercent(Double.parseDouble(feiYongZhanBi.getChargeYb()), Double.parseDouble(feiYongZhanBi.getTotalCharge())));
        }
        XinZhenYiZhu xinZhenYiZhu = yiZhuLuRuDao.queryPatientInfo(data.getInpatientNo(), data.getAdmissTimes());
        if (xinZhenYiZhu != null) {
            // 是否出纳
            data.setTimesBilled(xinZhenYiZhu.getTimesBilled());
        }
        if (null != data.getSocialNo() && data.getSocialNo().trim().length() == 18 && !data.getSocialNo().startsWith("K")) {
            try {
                // 根据身份证计算出生年龄
                data.setBirthDate(getBirthdayFromSocialNo(data.getSocialNo()));
            } catch (Exception e) {
                log.error("设置出生日期出错");
            }
        }
        data.setCrmName(getCrm(data.getSocialNo()));
        try {
            // 年龄
            data.setAge(DateUtil.calculateAge(new SimpleDateFormat("yyyy-MM-dd").parse(data.getBirthDate()), data.getAdmissDate()));
        } catch (Exception e) {
            log.error("计算年龄出错");
        }
    }

    private @NotNull String getCrm(String socialNo) {
        String chronicDiseaseTypes = dao.getCrmBySocialNo(socialNo);
        if (StringUtil.isBlank(chronicDiseaseTypes)) {
            return "";
        }
        String[] types = chronicDiseaseTypes.split(",");
        StringBuilder sb = new StringBuilder();
        for (String type : types) {
            sb.append(",'").append(type).append("'");
        }
        List<String> typeList = dao.getCrmTypeName(sb.substring(1));
        if (ListUtil.isBlank(typeList)) {
            return "";
        }
        return String.join("，", typeList);
    }

    private String getBirthdayFromSocialNo(String socialNo) {
        String birth = socialNo.substring(6, 14);
        String year = birth.substring(0, 4);
        String month = birth.substring(4, 6);
        String day = birth.substring(6, 8);
        return year + "-" + month + "-" + day;
    }

    public ResultVo<HashMap<String, Object>> getDisDiag(String inpatientNo, Integer admissTimes) {
        HashMap<String, Object> map = new HashMap<>(Capacity.TWO);
        map.put("yb", dao.getYibaoDisDiags(inpatientNo, admissTimes));
        map.put("bl", dao.getBingliDisDiags(inpatientNo, admissTimes));
        return ResultVoUtil.success(map);
    }

    public ResultVo<Map<String, Object>> getNotUploadedFees(GetFeesParam param) {
        Integer ledgerSn = routines.selectMaxLedgerSn(param.getPatNo(), param.getTimes());
        if (null == ledgerSn) {
            ledgerSn = 1;
        }
        IPage<NotUploadedFee> iPage = new Page<>(param.getCurrentPage(), param.getPageSize());
        Map<String, Object> map = new HashMap<>(Capacity.THREE);
        String serial1 = "00";
        String serial2 = "";
        if (param.getZdTable().equals(ZD_MEDCN)) {
            serial1 = "01";
            serial2 = "99";
        }
        if (param.getInjuryMode()) {
            iPage = routines.selectInjuryNotUploadedFees(iPage, param.getZdTable(), param.getPatNo(),
                    param.getTimes(), ledgerSn, DateUtil.getTodayEndTime(), serial1, serial2);
        } else {
            iPage = param.getZdTable().equals("yp_zd_dict") ?
                    routines.selectNotUploadedYpFees(iPage, param.getPatNo(),
                    param.getTimes(), ledgerSn, DateUtil.getTodayEndTime(), serial1, serial2)
                    :routines.selectNotUploadedXmFees(iPage, param.getPatNo(),
                    param.getTimes(), ledgerSn, DateUtil.getTodayEndTime(), serial1, serial2);
        }
        map.put("totalSize", iPage.getTotal());
        map.put("list", iPage.getRecords());
        map.put("sum", routines.selectSumChargeFee(param.getPatNo(), param.getTimes(), ledgerSn,
                DateUtil.getTodayEndTime(), serial1, serial2));
        return ResultVoUtil.success(map);
    }

    public ResultVo<Map<String, Object>> getIdCardInfo(String inpatientNo, Integer admissTimes) {
        Patient patient = dao.getPatientInfo(inpatientNo, "zy_actpatient", 0);
        if (null == patient) {
            patient = dao.getPatientInfo(inpatientNo, "zy_inactpatient", admissTimes);
        }
        String birthDate = DateUtil.calculateBirthDateFromIdNumber(patient.getSocialNo());
        if (null != birthDate) {
            patient.setBirthDate(birthDate);
        }
        List<IdCard> idCard = dao.selectIdCard(patient.getSocialNo());
        if (idCard.isEmpty()) {
            idCard = dao.getIdCard(inpatientNo, admissTimes);
            if (idCard.isEmpty()) {
                idCard = dao.getScanFile(inpatientNo, admissTimes);
            }
        }
        if (idCard.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有查询到此患者的身份证或扫描件，请检查身份证号是否有误。");
        }
        Map<String, Object> map = new HashMap<>();
        map.put("idCard", idCard.get(0));
        map.put("patient", patient);
        return ResultVoUtil.success(map);
    }

    /**
     * requestType: 1 - 取消医保登记申请  2 - 出院结算申请
     */
    public ResultVo<List<ToYbkRequest>> getCancelRegisterRequests(String inpatientNo, Integer admissTimes, Integer requestType) {
        // settleType: 0-其他,  1-已结算未出纳， 4-已出纳，  3-中间结算
        Integer settleType = dao.getSettleType(inpatientNo, admissTimes);
        if (settleType > 1) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "此患者已经出纳，不可进行取消医保登记的操作。");
        } else {
            return ResultVoUtil.success(dao.getRetractRequests(inpatientNo, admissTimes, requestType));
        }
    }

    public ResultVo<String> submitCancelRegisterRequest(ToYbkRequest param) {
        param.setInputId(TokenUtil.getInstance().getTokenUserId());
        Integer count = dao.getRequestCount(param.getInpatientNo(),
                param.getAdmissTimes(), param.getRequestType());
        param.setInputTimes(++count);
        log.info("提交取消医保登记请求>>> {}", param);
        dao.submitNewRequest(param);
        return ResultVoUtil.success();
    }

    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> submitSiPatientYbInfo(SubmitSiPtnt param) {
        Patient patient = param.getPatient();
        patient.setStaffId(TokenUtil.getInstance().getTokenUserId());
        MedType medType = MedType.get(patient.getMedType());
        if (null == medType) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请选择患者的医疗类别！");
        }
        if (medType == MedType.MATERNITY_HOSPITALIZATION) {
            if (StringUtil.isBlank(patient.getMatnType())) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "生育类别不能为空！");
            }
            if (StringUtil.isBlank(patient.getLatechbFlag())) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "是否晚育不能为空！");
            }
            if (StringUtil.isBlank(patient.getPretFlag())) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "是否早产不能为空！");
            }
        }
        if (medType == MedType.MATERNITY_HOSPITALIZATION) {
            if (StringUtil.isBlank(patient.getDiseCode())) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "患者病种不能为空！");
            }
        }
        if (StringUtil.isBlank(patient.getPsnCertType())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "证件类型不能为空！");
        }
        if (StringUtil.isBlank(patient.getDutyNurse())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "责任护士不能为空！");
        }
        if (StringUtil.isBlank(patient.getReferPhysician())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "管床医生不能为空！");
        }
        if (StringUtil.isBlank(patient.getCountry())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "国籍不能为空！");
        }
        if (StringUtil.isBlank(patient.getNation())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "民族不能为空！");
        }
        if (StringUtil.isBlank(patient.getContactName())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "联系人不能为空！");
        }
        if (StringUtil.isBlank(patient.getContactRelation())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "联系人关系不能为空！");
        }
        if (StringUtil.isBlank(patient.getContactAddrName())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "联系人地址不能为空！");
        }
        if (StringUtil.isBlank(patient.getContactPhone())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "联系人电话不能为空！");
        }
        Integer age = patient.getAge();
        if (patient.getPsnCertType().equals(PsnCertType.RESIDENT_IDENTITY_CARD.getCode())) {
            if (!IdCardUtil.isValidatedIdCard(patient.getSocialNo())) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "身份证不合法！");
            }
            age = IdCardUtil.getAgeByIdCard(patient.getSocialNo());
            patient.setSocialNo(patient.getSocialNo().toUpperCase());
        }
        if (null != age && (age < 16 || age > 60)) {
            if (patient.getName().equals(patient.getContactName()) ||
                    patient.getContactRelation().equals("0")) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "16岁以下或60岁以上的患者，联系人不能填写本人。");
            }
        }
        String zyh = patient.getInpatientNo();
        int times = patient.getAdmissTimes();
        for (int i = 0; i < param.getDiags().size(); i++) {
            ZyInYbDiag diag = param.getDiags().get(i);
            diag.setInpatientNo(zyh);
            diag.setAdmissTimes(times);
        }

        patient.setResponceType(medType.getResponceType());
        log.info("【操作员：{}】保存患者信息：{} ", patient.getStaffId(), param);
        if (dao.isBatjBa2Exist(patient.getInpatientNo(), patient.getAdmissTimes()) == 0) {
            dao.createBatjBa2(patient.getInpatientNo(), patient.getAdmissTimes(), patient.getDutyNurse());
        } else {
            dao.updateBatjBa2(patient.getInpatientNo(), patient.getAdmissTimes(), patient.getDutyNurse());
        }
        dao.updateZyActpatient(patient);
        dao.updateAPatientMi(patient);
        dao.deleteOldZyInYbDiag(zyh, times);
        if (ListUtil.notBlank(param.getDiags())) {
            for (ZyInYbDiag diag : param.getDiags()) {
                if (null == diag.getOpDate()) {
                    diag.setOpDate(new Date());
                }
            }
            dao.insertNewZyInYbDiag(patient.getStaffId(), param.getDiags());
        }
        return ResultVoUtil.success();
    }

    public ResultVo<List<ZyInYbDiag>> getZyInYbDiags(String inpatientNo, int admissTimes) {
        return ResultVoUtil.success(dao.getZyInYbDiag(inpatientNo, admissTimes));
    }

    public ResultVo<List<ZyDisYbDiag>> getZyDisYbDiags(String inpatientNo, int admissTimes) {
        return ResultVoUtil.success(dao.getZyDisYbDiags(inpatientNo, admissTimes));
    }

    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> saveZyInYbDiags(List<ZyInYbDiag> list) {
        final String opId = TokenUtil.getInstance().getTokenUserId();
        log.info("保存医保诊断表：操作员：{}，诊断：{}", opId, list);
        if (list == null || list.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "没有要保存的数据。");
        }
        final String inpatientNo = list.get(0).getInpatientNo();
        final Integer times = list.get(0).getAdmissTimes();
        dao.deleteOldZyInYbDiag(inpatientNo, times);
        dao.insertNewZyInYbDiag(opId, list);
        return ResultVoUtil.success();
    }

    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> saveSiZyInDiags(SaveSiZyDiags param) {
        param.setStaffId(TokenUtil.getInstance().getTokenUserId());
        log.info("保存医保诊断表：操作员：{}，诊断：{}", param.getStaffId(), param);
        if (param.getDiags() == null || param.getDiags().isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "没有要保存的数据。");
        }
        dao.deleteOldZyInYbDiag(param.getInpatientNo(), param.getAdmissTimes());
        dao.insertSiZyInYbDiag(param);
        return ResultVoUtil.success();
    }

    public ResultVo<String> genDismissActOrder(Patient param) {
        String disdate = dao.getActOrderDisDate(param.getInpatientNo(), param.getAdmissTimes());
        if (null != disdate) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "患者【" + param.getName() + "】已经存在出院医嘱！");
        }
        String staffId = TokenUtil.getInstance().getTokenUserId();
        float orderNo = dao.getActOrderNo();
        dao.updateActorOrderNo(orderNo + 1);
        dao.insertNewDismissActOrder(orderNo, param.getInpatientNo(), param.getAdmissTimes(),
                param.getDismissOrderDate(), staffId, param.getAdmissWard());
        List<ZyDisYbDiag> zyDisYbDiags = dao.getDisDiags(param.getInpatientNo(), param.getAdmissTimes());
        if (null == zyDisYbDiags || zyDisYbDiags.isEmpty()) {
            List<ZyInYbDiag> inYbDiags = dao.getZyInYbDiag(param.getInpatientNo(), param.getAdmissTimes());
            if (null == inYbDiags || inYbDiags.isEmpty()) {
                CodeName diag = dao.getAdmissDiag(param.getInpatientNo(), param.getAdmissTimes());
                dao.insertDisDiag(param.getInpatientNo(), param.getAdmissTimes(), diag.getCode(),
                        diag.getName(), staffId);
            } else {
                inYbDiags.forEach(itm -> {
                    itm.setSiDiagType(1);
                });
                dao.insertDisDiags(staffId, inYbDiags);
            }
        }
        return ResultVoUtil.success(String.valueOf(orderNo));
    }

    public ResultVo<Patient> receiveAndRecalculateCost(Patient p) {
        String zyh = p.getInpatientNo();
        int times = p.getAdmissTimes();
        int infant = zyh.startsWith("$") ? 1 : 0;
        int ledger = p.getLedgerSn();
//        dao.correctFeeChargeTimeBeforeAdmiss(zyh, times, p.getAdmissDate(), DateUtil.timePlusSecond(p.getAdmissDate(), 60));
        Date disdate = dao.selectActOrderDisDate(zyh, times);
        if (null != disdate) {
            // 如果费用发生时间小于入院时间那么就加一分钟。
            dao.correctFeeChargeTimeAfterDismiss(zyh, times, disdate);
        }
        dao.recountDeposit(zyh, times, ledger);
        dao.zyReceiveDrug(zyh, times, infant);
        dao.zyReceiveOne(zyh, times, infant);
        dao.zyCnglFyjsListYz(zyh, times);
        dao.updateZyDetailCharge(zyh, times, ledger);
        dao.zyCalcDetailAgainNew(zyh, times, ledger);
        dao.updateBalance(zyh, times, ledger);
        String balance = dao.selectLedgerBalance(zyh, times, ledger);
        if (StringUtil.isBlank(balance)) {
            balance = "0";
        }
        dao.updateZyActPatientBalance(zyh, balance);
        return getPatientInfo(zyh);
    }

    public ResultVo<ZyActpatient> getZyActpatient(String socialNo) {
        ZyActpatient zyActpatient = dao.getZyActpatient(socialNo);
        if (null == zyActpatient) {
            zyActpatient = new ZyActpatient();
        }
        return new ResultVo<>(zyActpatient);
    }
}
