package thyyxxk.webserver.service.inpatient.charge;

import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import thyyxxk.webserver.config.envionment.YzConfig;
import thyyxxk.webserver.config.exception.BizException;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.constants.sidicts.MedType;
import thyyxxk.webserver.dao.his.inpatient.charge.ForceInAndOutDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.inpatient.charge.forceinout.PatInquiry;
import thyyxxk.webserver.entity.inpatient.charge.forceinout.SimplePatient;
import thyyxxk.webserver.entity.login.UserInfo;
import thyyxxk.webserver.entity.medicalinsurance.injury.InjuryCareQualification;
import thyyxxk.webserver.entity.medicalinsurance.inpatient.ZyPatientInfo;
import thyyxxk.webserver.service.externalhttp.SiInjurySystem;
import thyyxxk.webserver.service.hutoolcache.DeptCache;
import thyyxxk.webserver.service.hutoolcache.UserCache;
import thyyxxk.webserver.service.medicalinsurance.SiZyService;

import java.util.Date;
import java.util.List;

@Service
@RequiredArgsConstructor
public class ForceInAndOutService {
    private final ForceInAndOutDao dao;
    private final DeptCache deptCache;
    private final UserCache userCache;
    private final SiZyService siZyService;
    private final SiInjurySystem injurySystem;
    private final CashierProcessService cashierService;
    private final YzConfig yzConfig;

    @Value("${si-injury-systm-url}")
    private String siInjurySystmUrl;


    public List<SimplePatient> getActpatient(PatInquiry inquiry) {
        List<SimplePatient> list;
        String input = inquiry.getUserInput() + "%";
        inquiry.setUserInput(input);
        if (inquiry.getPatStatus() == PatInquiry.PatStatus.IN_HOSPITAL) {
            list = dao.getZyActpatient(inquiry.getUserInput());
        } else {
            list = dao.getZyInactpatient(inquiry.getUserInput());
        }
        list.forEach(item -> {
            item.setWardName(deptCache.getDeptName(item.getWard()));
            item.setDeptName(deptCache.getDeptName(item.getDept()));
            item.setMedTypeName(MedType.getName(item.getMedType()));
        });
        return list;
    }

    @Transactional(rollbackFor = Exception.class)
    public String pullBack(SimplePatient patient) {
        int inHospCount = dao.getActpatientCount(patient.getPatNo());
        if (inHospCount > 0) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "有此患者的在院信息，无法进行召回。");
        }
        int bedFree = dao.certainBedFree(patient);
        if (bedFree == 0) {
            String maxFreeBedNo = dao.getMaxFreeBedNo(patient.getWard());
            if (StrUtil.isBlank(maxFreeBedNo)) {
                throw new BizException(ExceptionEnum.LOGICAL_ERROR, "病房已无空闲床位，无法进行召回！");
            }
            patient.setBedNo(maxFreeBedNo);
        }

        UserInfo user = userCache.getUserInfoByToken();
        patient.setStaffId(user.getCode());
        patient.setStaffName(user.getName());
        patient.setStaffOpType("recall");
        patient.setStaffOpTime(new Date());

        dao.changeBedNoAndBedStatus(patient);
        dao.transferToZyActpatient(patient);
        dao.transferToZyActpatientBaby(patient);
        dao.lockZyBedMi(patient);
        dao.clearZyAdt(patient);
        dao.deleteZyInactpatient(patient);
        dao.deleteZyInactpatientBaby(patient);
        dao.transferToYzActOrder(patient);
        dao.transferToYzActOrderBaby(patient);
        dao.deleteYzInactOrder(patient);
        dao.deleteYzInactOrderBaby(patient);
        dao.insertZyWorkLog(patient);

        return "患者召回成功。";
    }

    public String checkKckOutCondition(SimplePatient patient) {
        UserInfo user = userCache.getUserInfoByToken();
        Integer nbRole = yzConfig.getIgnoreDisOrderRole();
        if (null == nbRole || !user.getRoles().contains(nbRole)) {
            int disOrderCount = dao.getDisOrderCount(patient);
            if (disOrderCount == 0) {
                throw new BizException(ExceptionEnum.LOGICAL_ERROR,
                        "患者没有出院医嘱，无法进行出院处理。");
            }
        }
        Double cost = dao.getUnsettleCost(patient);
        if (null != cost && cost > 0) {
            return "病人有尚未结算的费用，确定出院吗？";
        }
        return "OK";
    }

    @Transactional(rollbackFor = Exception.class)
    public String kickOut(SimplePatient patient) {
        patient.setDisDate(new Date());
        patient.setStaffOpTime(patient.getDisDate());
        dao.updateZyActpatient(patient);
        dao.updateZyActpatientBaby(patient);
        dao.deleteZyInactpatient(patient);
        dao.transferToZyInactpatient(patient);
        dao.transferToZyInactpatientBaby(patient);
        dao.transferToYzInactOrder(patient);
        dao.transferToYzInactOrderBaby(patient);
        dao.deleteYzActOrder(patient);
        dao.deleteYzActOrderBaby(patient);
        dao.updateZyAdt(patient);
        dao.freeZyBedMi(patient);
        dao.deleteZyActpatient(patient);
        dao.deleteZyActpatientBaby(patient);

        UserInfo user = userCache.getUserInfoByToken();
        patient.setStaffId(user.getCode());
        patient.setStaffName(user.getName());
        patient.setStaffOpType("kickOut");

        dao.insertZyWorkLog(patient);

        return "患者出院成功。";
    }

    @Transactional(rollbackFor = Exception.class)
    public String revokeSettlement(SimplePatient patient) {
        UserInfo user = userCache.getUserInfoByToken();
        patient.setStaffId(user.getCode());
        patient.setStaffName(user.getName());
        patient.setLedgerSn(dao.getMaxLedgerSn(patient));
        // 0=未结算  1=出院结算  3=中间结算  4=已出纳
        String settleType = dao.getSettleType(patient);
        if (settleType.equals("0")) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "患者未结算，无法取消结算。");
        }
        if (settleType.equals("4")) {
            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "患者已出纳，请先取消出纳！");
        }

        MedType medType = MedType.get(patient.getMedType());
        if (medType != MedType.SELF_PAY) {
            String setlId = dao.getSetlId(patient);
            if (StrUtil.isBlank(setlId)) {
                medType = MedType.SELF_PAY;
            }
        }
        if (medType == MedType.SELF_PAY) {
            return revokeHisSettle(patient);
        }
        throw new BizException(ExceptionEnum.LOGICAL_ERROR,
                "患者已进行医保结算，请联系医保科，做取消医保结算操作。");
    }

    @Transactional(rollbackFor = Exception.class)
    public String revokeMedinsurSetl(SimplePatient patient) {
        UserInfo user = userCache.getUserInfoByToken();
        patient.setStaffId(user.getCode());
        patient.setStaffName(user.getName());
        patient.setLedgerSn(dao.getMaxLedgerSn(patient));
        ZyPatientInfo zyPatientInfo = new ZyPatientInfo();
        zyPatientInfo.setInpatientNo(patient.getPatNo());
        zyPatientInfo.setAdmissTimes(patient.getTimes());
        zyPatientInfo.setLedgerSn(patient.getLedgerSn());
        zyPatientInfo.setStaffId(user.getCode());
        siZyService.revokeSettlement(zyPatientInfo);
        return revokeHisSettle(patient);
    }

    private String revokeHisSettle(SimplePatient patient) {
        dao.clearZyLedgerFile(patient);
        dao.updateZyDetailCharge(patient);
        dao.deleteZyReceipt(patient);
        dao.deleteZyLedgerFileYb(patient);
        dao.deleteZyOweFile(patient);
        patient.setStaffOpTime(new Date());
        patient.setStaffOpType("revokeSettle");
        dao.insertZyWorkLog(patient);
        return "取消结算成功。";
    }
}
