package com.docus.server.message.busservice.impl;

import com.docus.core.util.DateUtil;
import com.docus.core.util.Func;
import com.docus.infrastructure.core.exception.BaseException;
import com.docus.infrastructure.web.api.CommonResult;
import com.docus.infrastructure.web.api.ResultCode;
import com.docus.server.message.busservice.MzsyBusinessService;
import com.docus.server.message.config.CollectTaskConfig;
import com.docus.server.message.config.MeiZhouSyQueryConfig;
import com.docus.server.message.converters.MzsyWsRecordSubmitMessageConvert;
import com.docus.server.message.converters.NkWsRecordSubmitMessageConvert;
import com.docus.server.message.dto.Message;
import com.docus.server.message.dto.MessageResponse;
import com.docus.server.message.dto.NkRecordSubmitDTO;
import com.docus.server.message.dto.TbasicQrPreciseCondition;
import com.docus.server.message.entity.TBasic;
import com.docus.server.message.feign.dto.CompensateTasRequest;
import com.docus.server.message.feign.dto.HospitalSubmitNodeLogAddDTO;
import com.docus.server.message.feign.enums.HospitalSubmitNodeEnum;
import com.docus.server.message.feign.service.CollectTaskService;
import com.docus.server.message.feign.service.HospitalSubmitNodeServiceApi;
import com.docus.server.message.mapper.TBasicMapper;
import com.docus.server.message.rpc.MeiZhouSyRpc;
import com.docus.server.message.rpc.request.MzSyArchiveRecallRequest;
import com.docus.server.message.validate.NkRecordSubmitValidate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;

/**
 * @BelongsProject: docus-unified-message
 * @BelongsPackage: com.docus.server.message.busservice.impl
 * @Author: chierhao
 * @CreateTime: 2024-03-20  08:57
 * @Description: TODO
 * @Version: 1.0
 */
@Slf4j
@Service
public class MzsyBusinessServiceImpl implements MzsyBusinessService {

    @Resource
    private TBasicMapper tBasicMapper;

    @Resource
    private MeiZhouSyRpc meiZhouSyRpc;

    @Resource
    private MeiZhouSyQueryConfig meiZhouSyConfig;

    @Autowired
    private HospitalSubmitNodeServiceApi hospitalSubmitNodeServiceApi;

    @Resource
    private CollectTaskService collectTaskService;
    @Override
    public MessageResponse recordSubmitHandle(Message message){
        try {
            CollectTaskConfig.TaskConfig taskConfig = CollectTaskConfig.getTaskConfig("WS_RECORD_SUBMIT");
            if (taskConfig == null || Func.isEmpty(taskConfig.getCollectorIds())) {
                throw new RuntimeException("任务配置未配置采集器id,WS_RECORD_SUBMIT");
            }
            NkRecordSubmitDTO dto = NkWsRecordSubmitMessageConvert.convert(message.getMessage());
            NkRecordSubmitValidate.verifyRecordSubmitDTO(dto);
            TbasicQrPreciseCondition condition = MzsyWsRecordSubmitMessageConvert.convert(dto);
            List<String> patientIds = tBasicMapper.getMzsyPatientIdByPreciseConditions(condition);
            verifyPatientIds(patientIds);

            String submitDate = dto.getSubmitDate();
            tBasicMapper.insertOrUpdateDoctorSubmitTime(patientIds.get(0), Func.parseDate(submitDate, DateUtil.PATTERN_DATETIME));

            compensateTask("电子病历提交",patientIds, taskConfig.getCollectorIds());
            tBasicMapper.updateEmrSubmitState(patientIds.get(0), 1);

            String submitName = dto.getSubmitName();
            String submitNo = dto.getSubmitNo();
            // 添加提交记录
            HospitalSubmitNodeLogAddDTO nodeLogAddDTO = new HospitalSubmitNodeLogAddDTO();
            nodeLogAddDTO.setPatientId(patientIds.get(0));
            nodeLogAddDTO.setContent(new String[]{submitDate});
            nodeLogAddDTO.setSubmitNodeEnum(HospitalSubmitNodeEnum.EMR);
            nodeLogAddDTO.setCreater(submitName+"("+submitNo+")");
            nodeLogAddDTO.setCreaterName(submitName+"("+submitNo+")");
            hospitalSubmitNodeServiceApi.addLog(nodeLogAddDTO);
            updateBackLogSubmitTime(patientIds.get(0));
            meiZhouSyRpc.archiveAndRecall(archiveRequest(patientIds.get(0),"EMR"));
            return new MessageResponse(ResultCode.SUCCESS.getCode(), success());
        } catch (BaseException baseException) {
            log.error(baseException.getMessage(), baseException);
            // 业务异常，不希望重试，直接消息返回错误
            MessageResponse response = new MessageResponse(ResultCode.FAILED.getCode(), fail(baseException.getMessage()));
            response.setRetry(0);
            return response;
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            // 不可知的错误，希望重试
            MessageResponse response = new MessageResponse(ResultCode.FAILED.getCode(), fail("系统错误"));
            response.setRetry(1);
            return response;
        }
    }



    @Override
    public MessageResponse nurseSubmitHandle(Message message) {
        try {
            CollectTaskConfig.TaskConfig taskConfig = CollectTaskConfig.getTaskConfig("WS_NURS_SUBMIT");
            if (taskConfig == null || Func.isEmpty(taskConfig.getCollectorIds())) {
                throw new RuntimeException("任务配置未配置采集器id,WS_NURS_SUBMIT");
            }
            NkRecordSubmitDTO dto = NkWsRecordSubmitMessageConvert.convert(message.getMessage());
            NkRecordSubmitValidate.verifyRecordSubmitDTO(dto);
            TbasicQrPreciseCondition condition = MzsyWsRecordSubmitMessageConvert.convert(dto);
            List<String> patientIds = tBasicMapper.getMzsyPatientIdByPreciseConditions(condition);
            verifyPatientIds(patientIds);

            String submitDate = dto.getSubmitDate();
            tBasicMapper.insertOrUpdateNurseSubmitTime(patientIds.get(0), Func.parseDate(submitDate, DateUtil.PATTERN_DATETIME));

            compensateTask("护理提交",patientIds, taskConfig.getCollectorIds());
            tBasicMapper.updateNursCollectState(patientIds.get(0), 1);

            String submitName = dto.getSubmitName();
            String submitNo = dto.getSubmitNo();
            // 添加提交记录
            HospitalSubmitNodeLogAddDTO nodeLogAddDTO = new HospitalSubmitNodeLogAddDTO();
            nodeLogAddDTO.setPatientId(patientIds.get(0));
            nodeLogAddDTO.setContent(new String[]{submitDate});
            nodeLogAddDTO.setSubmitNodeEnum(HospitalSubmitNodeEnum.NURSE);
            nodeLogAddDTO.setCreater(submitName+"("+submitNo+")");
            nodeLogAddDTO.setCreaterName(submitName+"("+submitNo+")");
            hospitalSubmitNodeServiceApi.addLog(nodeLogAddDTO);
            meiZhouSyRpc.archiveAndRecall(archiveRequest(patientIds.get(0),"NURSE"));
            return new MessageResponse(ResultCode.SUCCESS.getCode(), success());
        } catch (BaseException baseException) {
            log.error(baseException.getMessage(), baseException);
            // 业务异常，不希望重试，直接消息返回错误
            MessageResponse response = new MessageResponse(ResultCode.FAILED.getCode(), fail(baseException.getMessage()));
            response.setRetry(0);
            return response;
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            // 不可知的错误，希望重试
            MessageResponse response = new MessageResponse(ResultCode.FAILED.getCode(), fail("系统错误"));
            response.setRetry(1);
            return response;
        }
    }

    private void updateBackLogSubmitTime(String patientId) {
       Long id = tBasicMapper.getLastBackLogId(patientId);
       if(id != null){
           String time = Func.formatDateTime(LocalDateTime.now());
           tBasicMapper.updateBackLogSubmitTime(id,time);
       }
    }


    private void verifyPatientIds(List<String> patientIds) {
        if (Func.isEmpty(patientIds)) {
            throw new BaseException("系统无此患者！");
        }
        if (patientIds.size() > 1) {
            throw new BaseException("系统中患者有多个,无法确认！");
        }
    }

    private void compensateTask(String source,List<String> patientIds, List<String> collectorIds) {
        log.info("{},补偿任务 patientIds:{} collectId:{}",source, patientIds, collectorIds);
        CompensateTasRequest dto = new CompensateTasRequest();
        dto.setPatientIds(patientIds);
        dto.setCollectorIds(collectorIds);
        dto.setPriority(3);
        CommonResult<String> result = collectTaskService.compensateTask(dto);
        log.info("{}，补偿任务结果：{}", source,Func.toJson(result));
    }

    private String success() {
        return "<Response>" +
                "<RetInfo>" +
                "<RetCode>0</RetCode>" +
                "<RetCon>成功</RetCon>" +
                "</RetInfo>" +
                "</Response>";
    }

    private String fail(String message) {
        return "<Response>" +
                "<RetInfo>" +
                "<RetCode>1</RetCode>" +
                "<RetCon>" + message + "</RetCon>" +
                "</RetInfo>" +
                "</Response>";
    }





    /**
     *
     * 获取归档请求参数
     * @param patientId 病案主键
     * @param type 推送类型 EMR:电子病例，NURSE:护理
     * @return 归档请求参数
     */
    private MzSyArchiveRecallRequest archiveRequest(String patientId,String type) {
        return archiveRecallRequest(patientId,type,"1");
    }
    /**
     *
     * 获取解档请求参数
     * @param patientId 病案主键
     * @param type 推送类型 EMR:电子病例，NURSE:护理
     * @return 解档请求参数
     */
    private MzSyArchiveRecallRequest unarchiveRequest(String patientId,String type) {
        return archiveRecallRequest(patientId,type,"0");
    }
    /**
     *
     * 获取归档/解档请求参数
     * @param patientId 病案主键
     * @param type 推送类型 EMR:电子病例，NURSE:护理
     * @param archiveState  解档/归档状态 0:解档 1:归档
     * @return 归档/解档请求参数
     */
    private MzSyArchiveRecallRequest archiveRecallRequest(String patientId,String type,String archiveState) {
        String formatDateTime = Func.formatDateTime(new Date());
        TBasic basicInfo = tBasicMapper.getTBasicInfo(patientId);
        MzSyArchiveRecallRequest request = new MzSyArchiveRecallRequest();
        request.setType(type);
        request.setArchiveState(archiveState);
        request.setArchiveTime(basicInfo.getArchiveTime()==null?formatDateTime:Func.formatDateTime(basicInfo.getArchiveTime()));
        request.setAdmitTime(Func.formatDateTime(basicInfo.getAdmissDate()));
        request.setDisTime(Func.formatDateTime(basicInfo.getDisDate()));
        request.setDischargeDeptCode(basicInfo.getDisDept());
        request.setDischargeDeptName(basicInfo.getDisDeptName());
        request.setInHospIndexNo(basicInfo.getInpatientNo());
        request.setInHospNo(basicInfo.getJzh());
        request.setVisitNo(basicInfo.getAdmissTimes());
        request.setPatientName(basicInfo.getName());
        request.setUnarchiveTime(formatDateTime);
        request.setControlUserName(meiZhouSyConfig.getMedicalArchiveAndRecallWsdlUserCode());
        request.setControlName(meiZhouSyConfig.getMedicalArchiveAndRecallWsdlUserName());
        return request;
    }
}
