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.feign.service.CollectTaskService;
import com.docus.server.message.feign.dto.CompensateTasRequest;
import com.docus.server.message.busservice.SdBusinessService;
import com.docus.server.message.config.CollectTaskConfig;
import com.docus.server.message.dto.Message;
import com.docus.server.message.dto.MessageResponse;
import com.docus.server.message.mapper.TBasicMapper;
import com.docus.server.message.util.XmlUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.w3c.dom.Node;

import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class SdBusinessServiceImpl implements SdBusinessService {

    private CollectTaskService collectTaskService;
    private TBasicMapper tBasicMapper;

    @Autowired
    public void setCollectTaskService(CollectTaskService collectTaskService) {
        this.collectTaskService = collectTaskService;
    }

    @Autowired
    public void settBasicMapper(TBasicMapper tBasicMapper) {
        this.tBasicMapper = tBasicMapper;
    }

    @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");
            }
            RecordSubmitDTO recordSubmitDto = convert(message.getMessage());
            verifyRecordSubmitDTO(recordSubmitDto);
            List<String> patientIds = tBasicMapper.getPatientIdsByInpatientNoAndTimes(recordSubmitDto.getInHospIndexNo(), recordSubmitDto.getVisitNo());
            verifyPatientIds(patientIds);
            tBasicMapper.insertOrUpdateSubmitTime(patientIds.get(0),recordSubmitDto.getSubmitTime());
            compensateTask(patientIds, taskConfig.getCollectorIds());
            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 verifyRecordSubmitDTO(RecordSubmitDTO recordSubmitDto) {
        if (Func.isBlank(recordSubmitDto.getInHospIndexNo())) {
            throw new BaseException("住院号不能为空！");
        }
        if (Func.isEmpty(recordSubmitDto.getVisitNo())) {
            throw new BaseException("住院次数不能为空！");
        }
        if (Func.isEmpty(recordSubmitDto.getSubmitTime())) {
            throw new BaseException("提交时间不能为空！");
        }
        if (Func.isEmpty(recordSubmitDto.getInHospState())) {
            throw new BaseException("住院状态不能为空！");
        }
        if (recordSubmitDto.getInHospState() != 1) {
            throw new BaseException("住院状态需要为已出院！");
        }
    }

    private void compensateTask(List<String> patientIds, List<String> collectorIds) {
        CompensateTasRequest dto = new CompensateTasRequest();
        dto.setPatientIds(patientIds);
        dto.setCollectorIds(collectorIds);
        dto.setPriority(4);
        log.info("补偿电子病历任务 数据：{}", dto);
        CommonResult<String> task = collectTaskService.compensateTask(dto);
        if (ResultCode.FAILED.getCode().equals(task.getCode())) {
            throw new RuntimeException("补偿失败！");
        }
    }

    private void verifyPatientIds(List<String> patientIds) {
        if (Func.isEmpty(patientIds)) {
            throw new BaseException("住院号+住院次数 ，系统无此患者！");
        }
        if (patientIds.size() > 1) {
            throw new BaseException("住院号+住院次数 ，系统中患者有多个！");
        }
    }

    private RecordSubmitDTO convert(String str) {
         String inHospNo=null;
         String inHospIndexNo=null;
         Integer visitNo=null;
         String name=null;
         Date submitTime=null;
         Integer inHospState=null;

        XmlUtil xmlUtil = XmlUtil.of(str);
        try {
            // 住院状态 住院状态 0：在院 1：出院
            Node inHospStateNode = xmlUtil.getNode("/Request/Msg/INHOSP_STATE");
            inHospState=Integer.parseInt(inHospStateNode.getTextContent());
        }catch (Exception ex){
            throw new BaseException("解析住院状态出错！");
        }
        try {
            // 住院流水号
            Node inHospNoNode = xmlUtil.getNode("/Request/Msg/INHOSP_NO");
            inHospNo=inHospNoNode.getTextContent();
        } catch (Exception ex) {
            throw new BaseException("解析 住院流水号 出错！");
        }

        try {
            // 住院号
            Node inHospIndexNoNode = xmlUtil.getNode("/Request/Msg/INHOSP_INDEX_NO");
            inHospIndexNo=inHospIndexNoNode.getTextContent();
        } catch (Exception ex) {
            throw new BaseException("解析 住院号 出错！");
        }
        try {
            // 住院次数
            Node visitNoNode = xmlUtil.getNode("/Request/Msg/VISIT_NO");
            visitNo=Integer.parseInt(visitNoNode.getTextContent());
        } catch (Exception ex) {
            throw new BaseException("解析 住院次数 出错！");
        }
        try {
            // 患者姓名
            Node nameNode = xmlUtil.getNode("/Request/Msg/NAME");
            name=nameNode.getTextContent();
        } catch (Exception ex) {
            throw new BaseException("解析  出错！");
        }
        try {
            // 提交时间
            Node submitTimeNode = xmlUtil.getNode("/Request/Msg/SUBMIT_TIME");
            submitTime= DateUtil.parse(submitTimeNode.getTextContent(), DateUtil.PATTERN_DATETIME);
        } catch (Exception ex) {
            throw new BaseException("解析 提交时间 出错！");
        }

        RecordSubmitDTO recordSubmitDTO = new RecordSubmitDTO();
        recordSubmitDTO.setInHospNo(inHospNo);
        recordSubmitDTO.setVisitNo(visitNo);
        recordSubmitDTO.setInHospState(inHospState);
        recordSubmitDTO.setName(name);
        recordSubmitDTO.setInHospIndexNo(inHospIndexNo);
        recordSubmitDTO.setSubmitTime(submitTime);
        return recordSubmitDTO;
    }

    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>";
    }

    @Data
    private static class RecordSubmitDTO {
        // 住院流水号
        private String inHospNo;
        // 住院号
        private String inHospIndexNo;
        // 住院次数
        private Integer visitNo;
        // 患者姓名
        private String name;
        // 提交时间
        private Date submitTime;
        // 住院状态0：在院 1：出院
        private Integer inHospState;
    }
}
