package thyyxxk.webserver.service.zhuyuanyisheng.emr;

import com.alibaba.fastjson.JSON;
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.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import thyyxxk.webserver.config.auth.PassToken;
import thyyxxk.webserver.config.exception.BizException;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.dao.his.zhuyuanyisheng.emr.EmrControlDao;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.zhuyuanyisheng.emr.EmrLimitUnlock;
import thyyxxk.webserver.entity.zhuyuanyisheng.emrcontrolrule.*;
import thyyxxk.webserver.utils.*;

import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * @author Administrator
 */
@Service
@Slf4j
public class EmrControlRuleSever {

    private final EmrControlDao dao;

    public EmrControlRuleSever(EmrControlDao dao) {
        this.dao = dao;
    }


    @DS("his")
    public ResultVo<List<Map<String, Object>>> getAvailableObjects() {
        return ResultVoUtil.success(dao.getAvailableObjects());
    }

    public List<EmrRule> getRuleList() {
        List<EmrRule> list = dao.selectRules();
        if (ListUtil.isBlank(list)) {
            return new ArrayList<>();
        }
        list.forEach(item -> {
            item.setMedicalRecordCode(dao.selectEmrCodeByRuleId(item.getId()));
        });
        return list;
    }

    public ResultVo<String> switchQualityControl(String id, Integer offOn) {
        int num = dao.switchQualityControl(id, offOn);
        if (num > 0) {
            return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION);
        }
        return ResultVoUtil.success();
    }

    public ResultVo<String> deleteRuleById(String id) {
        dao.deleteRuleById(id);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION);
    }

    /**
     * 修改入院质控时间
     *
     * @param date 时间
     * @return 提示
     */
    public ResultVo<String> modifyTheAdmissionQualityControlTime(String date) {
        dao.setTheTime(date);
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION);
    }

    public ResultVo<String> getAdmissDate() {
        return ResultVoUtil.success(dao.getAdmissDate());
    }


    /**
     * 创建病历的限制
     *
     * @param code        病历编码
     * @param patNo       住院号
     * @param times       住院次数
     * @param doctorLevel 医生等级
     * @param id          病历id
     * @return 返回提示
     */
    public ResultVo<EmrRuleVerify> createRestrictions(String code, String patNo, Integer times, Integer doctorLevel, String id) {
        log.info("病历编码：{}，住院号：{}，住院次数：{}", code, patNo, times);
        EmrRuleVerify ruleVerify = new EmrRuleVerify();
        // 获取质控的list
        List<EmrRule> ruleList = dao.selectRuleByEmrCode(code);
        // 如果质控的list为空就可以创建
        if (ListUtil.isBlank(ruleList)) {
            ruleVerify.setFlag(false);
            return ResultVoUtil.success(ruleVerify);
        }
        for (EmrRule item : ruleList) {
            String sql = item.getSql().replace("${PATNO}", "'" + patNo + "'")
                    .replace("${TIMES}", "'" + times + "'");
            Map<String, Object> executeSql = dao.executeSql(sql);
            if (executeSql == null) {
                continue;
            }
            boolean whetherToTimeOut = false;
            if (doctorLevel == 1) {
                whetherToTimeOut = DateUtil.moreThanHours((Date) executeSql.get("date"), item.getPrescription());
                ruleVerify.setFlag(whetherToTimeOut);
            }
            if (doctorLevel > 1) {
                whetherToTimeOut = DateUtil.moreThanHours((Date) executeSql.get("date"), item.getSuperiorDoctorTime());
            }
            ruleVerify.setFlag(whetherToTimeOut);
            ruleVerify.setMessage(item.getPromptStatement());
            break;
        }

        log.info("ruleList：{}", JSON.toJSONString(ruleList));
        return ResultVoUtil.success(ruleVerify);
    }


    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> requestToUnlockMedicalRecords(EmrLimitUnlock param) {
        param.setApplicant(TokenUtil.getInstance().getTokenUserId());
        param.setApplicationTime(new Date());
        log.info("数据:{}", JSON.toJSONString(param));

        // 把原来地申请取消
        int count = dao.updateUnlockOld(param);
        String str = "申请成功，等待医务部审核。";
        if (count > 0) {
            str = "原申请已顶替，申请成功，等待医务部审核。";
        }
        int insert = dao.applicationUnlock(param);
        if (insert == 0) {
            throw new BizException(ExceptionEnum.ERROR_MESSAGE, "申请错误。");
        }
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION, str);
    }


    public ResultVo<IPage<EmrLimitUnlock>> getApplicationData(SelectUnlockParam param) {
        IPage<EmrLimitUnlock> iPage = new Page<>(param.getCurrentPage(), param.getPageSize(), param.getTotal() == 0);
        QueryWrapper<EmrLimitUnlock> qw = getEmrLimitUnlockQueryWrapper(param);
        return ResultVoUtil.success(dao.selectUnlock(iPage, qw));
    }

    @NotNull
    private static QueryWrapper<EmrLimitUnlock> getEmrLimitUnlockQueryWrapper(SelectUnlockParam param) {
        QueryWrapper<EmrLimitUnlock> qw = new QueryWrapper<>();
        if (ListUtil.notBlank(param.getDateRange())) {
            qw.ge("application_time", param.getDateRange().get(0));
            qw.lt("application_time", param.getDateRange().get(1));
        }
        if (param.getFlag() > -1) {
            qw.eq("state", param.getFlag());
        }
        return qw;
    }

    public void exportExcelUnlock(HttpServletResponse response, SelectUnlockParam param) {
        IPage<EmrLimitUnlock> iPage = new Page<>(param.getCurrentPage(), -1, false);
        QueryWrapper<EmrLimitUnlock> qw = getEmrLimitUnlockQueryWrapper(param);
        iPage = dao.selectUnlock(iPage, qw);
        if (ListUtil.isBlank(iPage.getRecords())) {
            return;
        }

        String[] title = {"住院号", "住院次数", "申请人", "申请时间", "申请权限", "申请编辑时间", "申请备注", "状态", "审核人", "审核时间", "审核备注"};
        String[][] content = new String[iPage.getRecords().size()][];
        for (int i = 0; i < iPage.getRecords().size(); i++) {
            content[i] = new String[title.length];
            EmrLimitUnlock index = iPage.getRecords().get(i);
            content[i][0] = index.getPatNo();
            content[i][1] = String.valueOf(index.getTimes());
            content[i][2] = index.getApplicantName();
            content[i][3] = DateUtil.formatDatetime(index.getApplicationTime());
            content[i][4] = index.getUnlockJson();
            content[i][5] = DateUtil.formatDatetime(index.getEffectiveTime());
            content[i][6] = index.getRequestRemarks();
            content[i][7] = index.getStateName();
            content[i][8] = index.getApproveName();
            content[i][9] = DateUtil.formatDatetime(index.getReviewTime());
            content[i][10] = index.getReviewNotes();
        }
        ExcelUtil.exportExcel(response, title, content);
        log.info("数据：{}", JSON.toJSONString(iPage));
    }

    public ResultVo<String> reviewMedicalRecordsToUnlock(EmrLimitUnlock param) {
        EmrLimitUnlock emrLimitUnlock = dao.selectUnlockById(param.getId());
        if (emrLimitUnlock.getState().equals(3)) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "该数据已经被申请人删除了，无法审核。");
        }
        if (emrLimitUnlock.getState().equals(param.getState())) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请勿重复操作。");
        }
        param.setApprove(TokenUtil.getInstance().getTokenUserId());
        dao.updateUnlockByIdNew(param);
        log.info("电子病历质控审核：{}", JSON.toJSONString(param));
        return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_NOTIFICATION);
    }

    public ResultVo<EmrLimitUnlock> getMyUnlockByPatNo(String patNo, Integer times) {
        return ResultVoUtil.success(dao.selectMyUnlockReqByPatNo(patNo, times, TokenUtil.getInstance().getTokenUserId()));
    }




}
