package com.docus.server.report.listener;

import com.alibaba.fastjson.JSON;
import com.docus.core.util.Func;
import com.docus.infrastructure.core.exception.BaseException;
import com.docus.infrastructure.redis.service.RedisOps;
import com.docus.infrastructure.web.api.CommonResult;
import com.docus.infrastructure.web.api.ResultCode;
import com.docus.server.collection.entity.TBasic;
import com.docus.server.collection.entity.TBasicExtend;
import com.docus.server.collection.mapper.TBasicMapper;
import com.docus.server.common.util.RedisKeyExpirationHandler;
import com.docus.server.common.util.RedisKeyExpirationListener;
import com.docus.server.report.api.MedicalRecordService;
import com.docus.server.report.api.request.CqcAuditRequest;
import com.docus.server.report.config.SdRyReportQueryConfig;
import com.docus.server.report.consts.ReportDownloadWait;
import com.docus.server.report.mapper.AfScanAssortMapper;
import com.docus.server.report.service.ShunDePeopleBusinessService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author WYBDEV
 */
@Component
@Slf4j
public class NisReportDownloadWaitHandler extends RedisKeyExpirationHandler {
    @Autowired
    private RedisKeyExpirationListener redisKeyExpirationListener;
    @Autowired
    private RedisOps redisOps;
    @Autowired
    private SdRyReportQueryConfig sdRyReportQueryConfig;
    @Autowired
    private TBasicMapper tBasicMapper;
    @Autowired
    private AfScanAssortMapper scanAssortMapper;
    @Resource
    private ShunDePeopleBusinessService shunDePeopleBusinessService;
    @Resource
    private MedicalRecordService medicalRecordService;

    @PostConstruct
    public void registerRedisKeyExpireListener() {
        redisKeyExpirationListener.register(this);
    }

    public static void main(String[] args) {
        String collectId = "3";
        String redisKey = String.format(ReportDownloadWait.REPORT_DOWNLOAD_WAIT_KEY, collectId, "20230501");
        System.out.println(redisKey);
        String redisKeyPrefix1 = String.format(ReportDownloadWait.REPORT_DOWNLOAD_WAIT_KEY, collectId, "");
        System.out.println(redisKey.startsWith(redisKeyPrefix1));
        // 得到病案主键
        System.out.println(redisKey.replace(redisKeyPrefix1, ""));
    }

    @Override
    public void businessHandle(String expireRedisKey) throws Exception {
        // 是否是护理采集要校验的redisKey，校验护理采集下载的文件数量是否和推送过滤后的匹配，匹配则调用 质控，不匹配发送异常信息
        if (!isNisReportWaitKey(expireRedisKey)) {
            return;
        }
        String patientId = getPatientId(expireRedisKey);
        log.info("病案主键：{} 护理采集数量校对开始！", patientId);
        boolean verifyNisFileCountResult = verifyNisFileCountAndPushErr(patientId);
        if (verifyNisFileCountResult) {
            tBasicMapper.updateNursCollectState(patientId,1);
            nisQualityControl(patientId);
        }
    }

    private boolean verifyNisFileCountAndPushErr(String patientId) {
        TBasic tBasic = tBasicMapper.getByPatientId(patientId);
        String inpatientNo = tBasic.getInpatientNo();
        Integer admissTimes = tBasic.getAdmissTimes();
        Integer submitNurseFileCount = tBasicMapper.getNurseFileCount(patientId);
        // 判断提交的文件数量
        if (submitNurseFileCount == null || submitNurseFileCount == 0) {
            log.warn("{} , {},未获取到护理提交的文件数量！", inpatientNo, admissTimes);
            shunDePeopleBusinessService.nurseFileCountError(inpatientNo, admissTimes, "未获取到护理提交的文件数量!");
            return false;
        }
        // 有些报告在采集的时候会过滤掉，有记录过滤的条数，计算实际应该要采集到的文件数量，和文件表数量做对比,文件表数量的小于应该采集到的，推送错误信息
        Integer nurseRemoveFileCount = tBasicMapper.getNurseRemoveFileCount(patientId);
        int realFileCount = submitNurseFileCount - nurseRemoveFileCount;
        String collectorId = sdRyReportQueryConfig.getReportQueryNurseInsertSugarCollectorId();
        Integer downloadSuccessFileCount = scanAssortMapper.countByPatientAndCollectorId(patientId, collectorId);
        if (downloadSuccessFileCount < realFileCount) {
            shunDePeopleBusinessService.nurseFileCountError(inpatientNo, admissTimes, "未完整采集该病案的文件！");
            return false;
        }
        return true;
    }

    private void nisQualityControl(String patientId) {

        TBasicExtend tBasicExtend = tBasicMapper.getTBasicExt(patientId);
        String dutyNurse = Objects.isNull(tBasicExtend) ? null : tBasicExtend.getDutyNurse();
        String qcNurse = Objects.isNull(tBasicExtend) ? null : tBasicExtend.getQcNurse();
        String dutyNurseName = Func.isBlank(dutyNurse) ? null : tBasicMapper.getNameByUserName(dutyNurse);
        String qcNurseName = Func.isBlank(qcNurse) ? null : tBasicMapper.getNameByUserName(qcNurse);

        CqcAuditRequest request1 = new CqcAuditRequest();
        request1.setType("1");
        request1.setPatientId(patientId);
        request1.setUserName(dutyNurse);
        request1.setName(dutyNurseName);
        CqcAuditRequest request2 = new CqcAuditRequest();
        request2.setType("2");
        request2.setPatientId(patientId);
        request2.setUserName(qcNurse);
        request2.setName(qcNurseName);

        List<CqcAuditRequest> request = new ArrayList<>(2);
        request.add(request1);
        request.add(request2);
        log.info("调用护理质控：{}", JSON.toJSONString(request));

        CommonResult<String> result = medicalRecordService.cqcAudit(request);
        log.info("{} 护理质控结果：{}", patientId, result);
        if (!ResultCode.SUCCESS.getCode().equals(result.getCode())) {
            throw new BaseException(result.getMsg());
        }
    }

    @Value("${docus.report.waittime}")
    private int waittime;

    @Override
    public void handleException(String expireRedisKey) {
        // 异常主键重新推送
        redisOps.setEx(expireRedisKey, "0", waittime*60);
    }

    /**
     * 是否是护理报告等待的redisKey
     *
     * @param expireRedisKey 过期的redisKey
     * @return 是否是护理报告等待的redisKey
     */
    private boolean isNisReportWaitKey(String expireRedisKey) {
        String collectorId = sdRyReportQueryConfig.getReportQueryNurseInsertSugarCollectorId();
        // 护理报告的key的前缀
        String nisKeyPrefix = String.format(ReportDownloadWait.REPORT_DOWNLOAD_WAIT_KEY, collectorId, "");
        return expireRedisKey.startsWith(nisKeyPrefix);
    }

    /**
     * 获取病案主键id
     */
    private String getPatientId(String expireRedisKey) {
        String collectorId = sdRyReportQueryConfig.getReportQueryNurseInsertSugarCollectorId();
        // 护理报告的key的前缀
        String nisKeyPrefix = String.format(ReportDownloadWait.REPORT_DOWNLOAD_WAIT_KEY, collectorId, "");
        return expireRedisKey.replace(nisKeyPrefix, "");
    }

}
