package thyyxxk.webserver.service.zhuyuanyisheng;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
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.springframework.stereotype.Service;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.constants.GetDateFormat;
import thyyxxk.webserver.dao.his.zhuyuanyisheng.ShouShuShenQingDao;
import thyyxxk.webserver.dao.his.zhuyuanyisheng.YiZhuLuRuDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.datamodify.GetDropdownBox;
import thyyxxk.webserver.entity.dictionary.CodeName;
import thyyxxk.webserver.entity.zhuyuanyisheng.query.ChaXunJianChaHeJianYan;
import thyyxxk.webserver.entity.zhuyuanyisheng.shoushu.*;
import thyyxxk.webserver.entity.zhuyuanyisheng.yizhuluru.XinZhenYiZhu;
import thyyxxk.webserver.service.PublicServer;
import thyyxxk.webserver.utils.*;

import java.util.*;

/**
 * <p>
 * 描述： 手术申请
 * </p>
 *
 * @author xc
 * @date 2022-02-22 15:45
 */
@Service
@Slf4j
public class ShouShuShenQingService {
    private final ShouShuShenQingDao dao;
    private final PublicServer publicServer;
    private final YiZhuLuRuDao yiZhuLuRuDao;

    public ShouShuShenQingService(ShouShuShenQingDao dao, PublicServer publicServer, YiZhuLuRuDao yiZhuLuRuDao) {
        this.dao = dao;
        this.publicServer = publicServer;
        this.yiZhuLuRuDao = yiZhuLuRuDao;
    }

    /**
     * 获取手术的项目 在
     *
     * @param name 搜索名称
     * @param type 搜索类型
     * @return
     */
    @DS("his")
    public ResultVo<List<ZdIcd9Cm3>> obtainSurgicalItems(String name, Integer type) {
        return ResultVoUtil.success(dao.obtainSurgicalItems(StringUtil.isContainChinese(name), type));
    }

    @DS("his")
    public ResultVo<List<CodeName>> getDoctorByOpCode(String opCode) {
        return ResultVoUtil.success(dao.getDoctorByOpCode(opCode));
    }


    @DS("his")
    public ResultVo<Boolean> preoperativeDiscussion(String patNo, Integer times, Integer count) {
        int currentPatientOpCount = dao.currentPatientOpCount(patNo, times);
        currentPatientOpCount += count;
        int currentEmrPreoperativelyDiscussCount = dao.currentEmrPreoperativelyDiscussCount(patNo, times);
        if (currentPatientOpCount > currentEmrPreoperativelyDiscussCount) {
            return ResultVoUtil.success(true);
        }
        return ResultVoUtil.success(false);
    }


    public ResultVo<List<GetDropdownBox>> shouShuShenQingCeBianLan() {
        return ResultVoUtil.success(dao.shouShuShenQingCeBianLan());
    }

    public ResultVo<List<Map<String, String>>> huoQuShouShuMingCheng(String patNo, Integer times, String name) {
        return ResultVoUtil.success(dao.huoQuShouShuMing(patNo, times, StringUtil.isContainChinese(name)));
    }

    public ResultVo<List<OpRecord>> getOpRecord(String patNo, Integer times) {
        QueryWrapper<OpRecord> qw = new QueryWrapper<>();
        qw.eq("inpatient_no", patNo);
        qw.eq("admiss_times", times);
        qw.ne("status", "d");
        qw.orderByDesc("apply_date");
        return ResultVoUtil.success(dao.selectOpRecord(qw));
    }

    public ResultVo<IPage<OpRecord>> huoQuShouShu(ChaXunJianChaHeJianYan param) {
        IPage<OpRecord> page = new Page<>(param.getCurrentPage(), param.getPageSize(), param.getTotal() == 0);
        QueryWrapper<OpRecord> qw = new QueryWrapper<>();
        qw.select("op_name, op_datetime, status,record_id");
        qw.eq("inpatient_no", param.getPatNo());
        qw.eq("admiss_times", param.getTimes());
        if (StringUtil.notBlank(param.getStartTime())) {
            qw.ge("req_date", param.getStartTime());
            qw.le("req_date", param.getEndTime());
        }
        if (StringUtil.notBlank(param.getOrderName())) {
            qw.eq("op_name", param.getOrderName());
        }
        qw.ne("status", "d");
        dao.selectPage(page, qw);
        return ResultVoUtil.success(page);
    }

    public ResultVo<JSONObject> getSurgeryDetail(String patNo, Integer times, Integer recordId) {
        OpRecord op = dao.daYingShouShu(patNo, times, recordId);
        List<TReqSurgicalDiag> list = dao.selectReqSurgicalDiagByReqNo(recordId);
        JSONObject json = new JSONObject();

        if (ListUtil.isBlank(list)) {
            TReqSurgicalDiag tReqSurgicalDiag1 = new TReqSurgicalDiag() {{
                setReqNo(recordId);
                setSort(1);
                setCode(op.getOpCode());
                setName(op.getOpName());
                setType(1);
            }};

            list.add(tReqSurgicalDiag1);
            TReqSurgicalDiag tReqSurgicalDiag2 = new TReqSurgicalDiag() {{
                setReqNo(recordId);
                setSort(1);
                setCode(op.getDiagBeforeCode());
                setName(op.getDiagBeforeOp());
                setType(2);
            }};
            list.add(tReqSurgicalDiag2);
        }

        json.put("opRecord", op);
        json.put("list", list);
        return ResultVoUtil.success(json);
    }

    @Deprecated
    public ResultVo<OpRecord> huoQuShouShuShenQingDaYing(String patNo, Integer times, Integer recordId) {
        OpRecord op = dao.daYingShouShu(patNo, times, recordId);
        if (op == null) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "该手术可能已经被删除了。");
        }

        try {
            EntityCopy.Copy(dao.daYingHuanZheXinXi(patNo, times), op);
        } catch (Exception e) {
            e.printStackTrace();
        }
        op.setAge(Objects.requireNonNull(DateUtil.calculateAge(DateUtil.parse(op.getBirthDate(), GetDateFormat.DATE), null)).toString());
        return ResultVoUtil.success(op);
    }

    public ResultVo<IPage<ShouShuFanHui>> fenLeiXiangQing(String code, String name, long total, long currentPage, long pageSize) {
        IPage<ShouShuFanHui> page = new Page<>(currentPage, pageSize, total == 0);
        page = dao.fenLeiXiangQing(page, code, StringUtil.isContainChinese(name));
        return ResultVoUtil.success(page);
    }

    /**
     * 远程搜索手术部位
     *
     * @param name 名字
     * @return 返回
     */
    @DS("his")
    public ResultVo<List<GetDropdownBox>> huoQuShouShuBuWei(String name) {
        if (StringUtil.isBlank(name)) {
            return ResultVoUtil.success(dao.huoQuShouShuBuWei(name));
        }
        return ResultVoUtil.success(dao.huoQuShouShuBuWei(StringUtil.isContainChinese(name)));
    }

    public ResultVo<String> applicationOpRecord(XinZengShouShu ss) {
        String error = applyForVerification(ss.getOpRecord());
        if (StringUtil.notBlank(error)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, error);
        }

        publicServer.huanZheJieSuan(ss.getInpatientNo(), ss.getAdmissTimes());
        String userCode = TokenUtil.getInstance().getTokenUserId();
        // 申请次数
        Integer reqNo = dao.shouShuShenQingCiShu(ss.getInpatientNo(), ss.getAdmissTimes()) + 1;
        OpRecord op = ss.getOpRecord();

        Integer recordId = publicServer.huoQuShouShuHao();

        op.setRecordId(recordId);
        op.setActOrderNo(publicServer.getActOrderNo());
        op.setOpTimes(reqNo);

        String msgContent = String.format("手术名称：<span style='color:#409eff'>【%s】</span><br>" +
                "手术时间：<span style='color:#409eff'>【%tF %<tT】</span><br>", op.getOpName(), op.getOpDatetime());

        XinZhenYiZhu patInfo = yiZhuLuRuDao.queryPatientInfo(ss.getInpatientNo(), ss.getAdmissTimes());
        String yzCode = ss.getGenerateRejectedOrders() ? "06054" : "10399";

        List<TReqSurgicalDiag> reqSurgicalDiagList = new ArrayList<>();
        reqSurgicalDiagList.addAll(surgicalDiagnosisFor(ss.getOpCodeList(), recordId, TReqSurgicalDiag.SURGERY));
        reqSurgicalDiagList.addAll(surgicalDiagnosisFor(ss.getDiagList(), recordId, TReqSurgicalDiag.DIAGNOSIS));

        try {
            dao.insertOpRecordJoin(op);
            dao.insertOpRecord(op,
                    ss.getInpatientNo(),
                    ss.getName(),
                    ss.getAdmissTimes(),
                    patInfo.getZkWard(),
                    patInfo.getDeptCode(),
                    userCode,
                    ss.getBedNo(),
                    ss.getAdmissWard());
            dao.insertYzOrderData(op, patInfo, userCode, ss.getExecDept(), yzCode);
            dao.insertReqSurgicalDiag(reqSurgicalDiagList);
        } catch (Exception e) {
            dao.delOpRecord(op.getRecordId(), op.getActOrderNo());
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "手术申请错误，请联系管理员", e.getMessage());
        }

        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }

    private List<TReqSurgicalDiag> surgicalDiagnosisFor(List<CodeName> list, int recordId, int type) {
        List<TReqSurgicalDiag> temp = new ArrayList<>();
        int index = 0;
        for (CodeName codeName : list) {
            TReqSurgicalDiag a = new TReqSurgicalDiag();
            a.setReqNo(recordId)
                    .setCode(codeName.getCode())
                    .setName(codeName.getName())
                    .setType(type)
                    .setSort(++index);
            temp.add(a);
        }
        return temp;
    }


    public String applyForVerification(OpRecord param) {
        StringBuilder sb = new StringBuilder();

        if (StringUtil.isBlank(param.getOpCode())) {
            sb.append("手术编码不能为空。");
        }
        if (param.getOpDatetime() == null) {
            sb.append("手术时间不能为空。");
        } else if (DateUtil.shiJianDaXiao(param.getOpDatetime(), param.getApplyDate(), "<")) {
            sb.append("手术时间不能小于申请时间。");
        }
        if (StringUtil.isBlank(param.getDiagBeforeCode())) {
            sb.append("术前诊断不能为空。");
        }
        if (StringUtil.isBlank(param.getPartCode())) {
            sb.append("手术部位不能为空。");
        }
        if (StringUtil.isBlank(param.getDoctorZd())) {
            sb.append("主刀医生不能为空。");
        }
        if (StringUtil.isBlank(param.getOpScale())) {
            sb.append("手术等级不能为空。");
        }
        if (StringUtil.isBlank(param.getOrderName())) {
            sb.append("生成的医嘱名不能为空。");
        }
        return sb.toString();
    }


    public ResultVo<String> shanChuShouShu(Integer recordId) {
        OpRecord op = dao.shouShuXinXi(recordId);
        if (op == null) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "没有找到该手术的信息。");
        }
        if (!"1".equals(op.getStatus().trim())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "无法删除该手术。");
        }
        dao.genXingShanChuBiaoZhi(recordId);
        log.info("删除手术==》操作人：{}，申请单号：{}", TokenUtil.getInstance().getTokenUserId(), recordId);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }

    public ResultVo<String> addASurgicalSite(String name) {
        if (dao.repeatPartName(name)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "手术部位名称重复");
        }
        String maxCode = String.valueOf(dao.getTheMaximumSurgicalCode() + 1);
        String newCode = maxCode.length() > 1 ? maxCode : '0' + maxCode;
        dao.insertNewSurgicalSite(newCode, name, PingYinUtils.pyShouZiMuDaXie(name), PingYinUtils.getWBCode(name));
        log.info("新增手术部位==>操作人:{}", TokenUtil.getInstance().getTokenUserId());
        return ResultVoUtil.success(newCode);
    }

    public ResultVo<String> removeSurgicalSite(String code) {
        dao.removeSurgicalSite(code);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE);
    }
}
