package thyyxxk.webserver.service.medicaladvice.patientinfo;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import thyyxxk.webserver.config.envionment.YzConfig;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.dao.his.inpatient.PatientDao;
import thyyxxk.webserver.dao.his.medicaladvice.patientinfo.AdjustBedDao;
import thyyxxk.webserver.dao.his.medicaladvice.patientinfo.ZkManageDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.executeItem.NumberEnum;
import thyyxxk.webserver.entity.inpatient.ZyActpatient;
import thyyxxk.webserver.entity.medicaladvice.medicamanage.patientinfo.ZkBedVo;
import thyyxxk.webserver.entity.medicaladvice.medicamanage.patientinfo.ZyBedMi;
import thyyxxk.webserver.entity.zhuyuanyisheng.ZyOrderZk;
import thyyxxk.webserver.service.hutoolcache.DeptCache;
import thyyxxk.webserver.service.zhuyuanyisheng.YiZhuLuRuServer;
import thyyxxk.webserver.utils.AssertUtil;
import thyyxxk.webserver.utils.CommonUtil;
import thyyxxk.webserver.utils.ResultVoUtil;
import thyyxxk.webserver.utils.TokenUtil;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author:lihong
 * @Date: 2024/1/3
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ZkManageService {
    private final ZkManageDao dao;
    private final PatientDao patientDao;
    private final AdjustBedDao adjustBedDao;
    private final DeptCache deptCache;
    private final RestTemplate template;
    private final YzConfig yzConfig;
    private final YiZhuLuRuServer yiZhuLuRuServer;

    public List<ZyActpatient> queryZkPatient(Map<String, String> query) {
        AssertUtil.isnotBlank(query.get("wardCode"), "病室编码不能为空");
        List<ZyActpatient> list = dao.selectZkPatient(query.get("keyWard"), query.get("wardCode"));
        CommonUtil.BeanTrim(list);
        return list;
    }

    public List<ZkBedVo> queryZkBedVo(Map<String, String> query) {
        AssertUtil.isnotBlank(query.get("wardCode"), "病室编码不能为空");
        List<ZkBedVo> list = dao.selectZkBedVo(query.get("wardCode"));
        CommonUtil.BeanTrim(list);
        return list;
    }

    public ResultVo<String> checkZk(ZkBedVo param) {
        AssertUtil.isnotBlank(param.getInpatientNo(), "住院号不能为空");
        AssertUtil.isnotBlank(param.getAdmissTimes(), "住院次数不能为空");
        AssertUtil.isnotBlank(param.getWardCode(), "病室不能为空");
        AssertUtil.isnotBlank(param.getDeptCode(), "转科病室不能为空");
        AssertUtil.isnotBlank(param.getZkDept(), "小科室不能为空");
        if (!passZk(param)) {
            Map<String, Object> map = dao.selectZkYz(param);
            if (CollUtil.isEmpty(map) || Convert.toInt(map.get("zk_count"), 0) == 0) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, StrUtil.format("{}病人没有转科医嘱,不可做转科处理!", param.getInpatientNo()));
            }
            ZyOrderZk zyOrderZk = dao.selectZkOrder(Convert.toBigDecimal(map.get("act_order_no")));
            if (zyOrderZk == null) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, StrUtil.format("{}病人没有转科医嘱详情,请确认!", param.getInpatientNo()));
            }

            if (!param.getDeptCode().equals(zyOrderZk.getNewWard()) || !param.getZkDept().equals(zyOrderZk.getNewDept())) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, StrUtil.format("{}病人选择的转科病区或小科室不对,正确的转科医嘱为病区:[{}],小科室:[{}]!",
                        param.getInpatientNo(), deptCache.getDeptName(zyOrderZk.getNewWard()), deptCache.getDeptName(zyOrderZk.getNewDept())));
            }
            Integer countZk = dao.selectZyZkList(param.getInpatientNo(), param.getAdmissTimes(), Convert.toBigDecimal(map.get("act_order_no")));
            if (countZk > 0) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, StrUtil.format("{}病人已经转科,请不要重复操作!", param.getInpatientNo()));
            }
        }
        Integer count = dao.countYd(param);
        Integer countTy = dao.sumTy(param);
        if (count > 0 || (countTy != null && countTy > 0)) {
            List<BigDecimal> detailYd = dao.detailYd(param);
            if (CollUtil.isNotEmpty(detailYd)) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, StrUtil.format("{}病人还有未提交的药单,医嘱号为:[{}],请先处理!", param.getInpatientNo(), CollUtil.join(detailYd, ",")));
            }
            List<BigDecimal> detailty = dao.detailTy(param);
            if (CollUtil.isNotEmpty(detailty)) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, StrUtil.format("{}病人还有未退药品,医嘱号为:[{}],请先处理!", param.getInpatientNo(), CollUtil.join(detailty, ",")));
            }
        }
        //接收药品
        int infant = param.getInpatientNo().contains("$") ? 1 : 0;
        patientDao.zyReceiveDrug(param.getInpatientNo(), param.getAdmissTimes(), infant);
        //接收医嘱
        patientDao.zyReceiveOne(param.getInpatientNo(), param.getAdmissTimes(), infant);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "药品和医嘱接收成功!");
    }

    private boolean passZk(ZkBedVo param) {
        String SJ_DEPT_CODE = yzConfig.getShoushubingqu();
        return SJ_DEPT_CODE != null && (SJ_DEPT_CODE.equals(param.getDeptCode()) || SJ_DEPT_CODE.equals(param.getWardCode()));
    }

    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> saveZkData(List<ZkBedVo> param) {
        List<ZkBedVo> data = param.stream().filter(item -> StrUtil.isNotBlank(item.getInpatientNo())).collect(Collectors.toList());
        AssertUtil.isnotBlank(data, "保存数据不能为空");
        String userId = TokenUtil.getInstance().getTokenUserId();
        for (ZkBedVo item : data) {
            AssertUtil.isnotBlank(item.getZkDept(), StrUtil.format("{}病人转科科室不能为空!", item.getInpatientNo()));
            int count = 0;
            if (!item.getInpatientNo().contains("$")) {
                count = dao.countBaby(item.getInpatientNo() + "$%");
            }
            if (count > 0) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, StrUtil.format("{}病人有婴儿信息,不可做转科处理!", item.getInpatientNo()));
            }
            Integer hasBedNo = adjustBedDao.isIdleBedNo(item.getBedNo(), item.getWardCode());
            if (hasBedNo == null) {
                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, StrUtil.format("{}病人转科的床位已经有病人了,请刷新重新分配床位!", item.getInpatientNo()));
            }
            //清空原床位
            ZyBedMi zyBedMi = new ZyBedMi();
            zyBedMi.setInpatientNo(null);
            zyBedMi.setAdmissTimes(null);
            zyBedMi.setBedStatus(NumberEnum.ONE.getCode());
            zyBedMi.setBedNo(item.getOrigBed());
            zyBedMi.setDeptCode(item.getOrigDept());
            zyBedMi.setWardCode(item.getOrigDept());
            adjustBedDao.updatePatientByBed(zyBedMi);
            //给专科后的床位
            ZyBedMi tempBed = new ZyBedMi();
            tempBed.setInpatientNo(item.getInpatientNo());
            tempBed.setAdmissTimes(item.getAdmissTimes());
            tempBed.setBedStatus(NumberEnum.TWO.getCode());
            tempBed.setDeptCode(item.getWardCode());
            tempBed.setWardCode(item.getWardCode());
            tempBed.setBedNo(item.getBedNo());
            adjustBedDao.updatePatientByBed(tempBed);
            //修改在院表的转科科室
            dao.updateZkZyActpatien(item);
            dao.insertZyAdt(item);
            item.setOpId(userId);
            String SJ_DEPT_CODE = yzConfig.getShoushubingqu();
            if (SJ_DEPT_CODE != null && (SJ_DEPT_CODE.equals(item.getOrigDept()) || SJ_DEPT_CODE.equals(item.getWardCode()))) {
                dao.insertZyZkListNoActOrderNo(item);
            } else {
                dao.insertZyZkList(item);
            }
            yiZhuLuRuServer.updateChargeByWardCode(item.getInpatientNo(), item.getAdmissTimes());
        }
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "保存成功");
    }

    public ResultVo<String> createPatientDoor(List<ZkBedVo> param) {
        for (ZkBedVo zkBedVo : param) {
            try {
                Map<String, Object> paramMap = new HashMap<>();
                paramMap.put("patNo", StrUtil.trim(zkBedVo.getInpatientNo()));
                template.postForObject("http://172.16.32.167:20923/thyy/api/haikang/door/createPatient", paramMap, ResultVo.class);
            } catch (Exception e) {
                log.error("住院号=" + zkBedVo.getInpatientNo() + "创建门禁报错,{}", e);
            }
        }
        return ResultVoUtil.success();
    }
}
