package com.docus.server.report.webservice.impl;

import com.docus.core.util.DateUtil;
import com.docus.core.util.Func;
import com.docus.infrastructure.core.exception.BaseException;
import com.docus.infrastructure.redis.service.RedisOps;
import com.docus.server.report.api.ShunDePeopleService;
import com.docus.server.report.api.dto.ReportDto;
import com.docus.server.report.config.SdRyReportHandledConfig;
import com.docus.server.report.config.ZdAssortConfig;
import com.docus.server.report.job.FetchPacsBase64Job;
import com.docus.server.report.job.ReportJob;
import com.docus.server.report.service.ReportService;
import com.docus.server.report.util.IdUtil;
import com.docus.server.report.util.XmlUtil;
import com.docus.server.report.webservice.WebserviceMessageType;
import com.docus.server.report.webservice.WebserviceReceiveServerHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.w3c.dom.Node;

import javax.annotation.Resource;
import java.util.Date;

/**
 * HIP1008-检查报告新增服务处理
 *
 * @author jiahsi
 */
@Service(WebserviceMessageType.HIP1008)
@Slf4j
public class HIP1008InspectionReportAdditionHandler implements WebserviceReceiveServerHandler {
    @Resource
    private ReportService reportService;
    @Resource
    private ShunDePeopleService shunDePeopleService;
    @Resource
    private ReportJob reportJob;
    @Resource
    private RedisOps redisOps;


    @Override
    public String handle(String receiveMessage) {
        log.info("收到检查报告新增消息：{}", receiveMessage);
        String msgId = "";
        String sender = "";
        String receiver = "";
        try {
            XmlUtil xmlUtil = XmlUtil.of(receiveMessage);
            msgId = xmlUtil.getNode("/POOR_HIP1008/id/@extension").getNodeValue();
            sender = xmlUtil.getNode("/POOR_HIP1008/sender/device/id/item/@extension").getNodeValue();
            receiver = xmlUtil.getNode("/POOR_HIP1008/receiver/device/id/item/@extension").getNodeValue();
            SdRyReportHandledConfig sdRyReportHandledConfig = new SdRyReportHandledConfig();
            // 如果是获取base64的，为什么这里要解析，因为这里可以提前解析知道问题，base64另外抽出来的方法，会响应超时，为了做异步
            ReportDto reportDto = getReportDtoByInspectionInsert(xmlUtil);
            verifyFileInfo(reportDto);
            String sysFlag = reportDto.getSysFlag();
            if (sdRyReportHandledConfig.isNotHandled(sysFlag)) {
                return insertSuccess(msgId, sender, receiver);
            }
            if (sdRyReportHandledConfig.isBlocking(sysFlag)) {
                reportDto.setDownUrl(null);
                reportService.reportBuffer(reportDto);
                return insertSuccess(msgId, sender, receiver);
            }
            if (sdRyReportHandledConfig.isFetchBase64(sender)) {
                // 过程很长，保存队列，job慢慢消费
                redisOps.lPush(FetchPacsBase64Job.FETCH_PACS_BASE64_QUEUE_HIP1008,receiveMessage);
                return insertSuccess(msgId, sender, receiver);
            }
            reportService.report(reportDto);
            return insertSuccess(msgId, sender, receiver);
        } catch (BaseException baseException) {
            log.error(baseException.getMessage(), baseException);
            return insertFailed(msgId, sender, receiver, baseException.getMessage());
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            return insertFailed(msgId, sender, receiver, "系统错误！");
        }
    }

    public ReportDto fetchBase64Parse(XmlUtil inspectionInsertXmlUtil) {
        Node senderNode = inspectionInsertXmlUtil.getNode("/POOR_HIP1008/sender/device/id/item/@extension");
        String updateBy = senderNode.getNodeValue();


        Node inpatientNoNode = inspectionInsertXmlUtil.getNode("/POOR_HIP1008/controlActProcess/subject/recordTarget/patientRole/id[@root='2.16.156.10011.1.12']/@extension");
        String inpatientNo = inpatientNoNode.getNodeValue();

        Node admissTimesNode = inspectionInsertXmlUtil.getNode("/POOR_HIP1008/controlActProcess/subject/recordTarget/patientRole/item[@root='1.2.156.112635.1.2.1.7']/@extension");
        Integer admissTimes = Integer.valueOf(admissTimesNode.getNodeValue());

        // 患者本次就诊唯一键：患者id【12位】+就诊次数
        Node visitSnNode = inspectionInsertXmlUtil.getNode("/POOR_HIP1008/controlActProcess/subject/recordTarget/patientRole/id[@root='2.16.156.10011.1.11']/@extension");
        String visitSn = visitSnNode.getNodeValue();

        // 患者id
        Node patientSnNode = inspectionInsertXmlUtil.getNode("/POOR_HIP1008/controlActProcess/subject/recordTarget/patientRole/item[@root='2.16.156.10011.0.2.2']/@extension");
        String patientSn = patientSnNode.getNodeValue();

        // 检查报告单号标识
        Node reportFlagNode = inspectionInsertXmlUtil.getNode("/POOR_HIP1008/controlActProcess/subject/recordTarget/patientRole/id[@root='2.16.156.10011.1.32']/@extension");
        String examReportSn = reportFlagNode.getNodeValue();
        //电子申请单编号
        Node eafNoNode = inspectionInsertXmlUtil.getNode("/POOR_HIP1008/controlActProcess/subject/recordTarget/patientRole/id[@root='2.16.156.10011.1.24']/@extension");
        String requestSn = eafNoNode.getNodeValue();


        Node fileTitleNode = inspectionInsertXmlUtil.getNode("/POOR_HIP1008/controlActProcess/subject/component/structuredBody/component[@displayName='检查结果明细']/section/entry[@displayName='检查项目']/organizer/component[@displayName='检查项目']/observation/value");
        String reportName = fileTitleNode.getTextContent();


        ReportDto reportDto = new ReportDto();
        reportDto.setAdmisstimes(admissTimes);
        reportDto.setInpatientNo(inpatientNo);
        // 确定报告唯一 报告单号+申请单号
        reportDto.setSerialnum(examReportSn + requestSn);
        reportDto.setFileTitle(reportName);
        reportDto.setVisitSn(visitSn);
        reportDto.setPatientSn(patientSn);

        // 检查报告需要从Pacs接口获取base64
        String[] split = examReportSn.split("_");
        String fromPacs = shunDePeopleService.getBase64PdfFromPacs(split[0], split[1]);
        // 从pacs打印出来
        String base64 = reportJob.parsePacsGetBase64(fromPacs);
        if (Func.isBlank(base64)) {
            return null;
        }
        String url = reportJob.saveBase64(base64);
        reportDto.setDownUrl(url);
        reportDto.setDowntype(5);
        // 根据系统来分类
        reportDto.setAssortId(ZdAssortConfig.getZdAssortId(updateBy));
        reportDto.setSysFlag(updateBy);
        reportDto.setFileSource("1");
        reportDto.setFilestoragetype("1");
        return reportDto;
    }

    public ReportDto getReportDtoByInspectionInsert(XmlUtil inspectionInsertXmlUtil) {
        Node senderNode = inspectionInsertXmlUtil.getNode("/POOR_HIP1008/sender/device/id/item/@extension");
        String sender = senderNode.getNodeValue();
        String zdAssortId = ZdAssortConfig.getZdAssortId(sender);
        if (Func.isBlank(zdAssortId)) {
            zdAssortId = ZdAssortConfig.getOtherAssortId();
        }

        Node inpatientNoNode = inspectionInsertXmlUtil.getNode("/POOR_HIP1008/controlActProcess/subject/recordTarget/patientRole/id[@root='2.16.156.10011.1.12']/@extension");
        String inpatientNo = inpatientNoNode.getNodeValue();

        Node admissTimesNode = inspectionInsertXmlUtil.getNode("/POOR_HIP1008/controlActProcess/subject/recordTarget/patientRole/item[@root='1.2.156.112635.1.2.1.7']/@extension");
        Integer admissTimes = Integer.valueOf(admissTimesNode.getNodeValue());

        // 检查报告单号标识
        Node reportFlagNode = inspectionInsertXmlUtil.getNode("/POOR_HIP1008/controlActProcess/subject/recordTarget/patientRole/id[@root='2.16.156.10011.1.32']/@extension");
        String reportFlag = reportFlagNode.getNodeValue();
        //电子申请单编号
        Node eafNoNode = inspectionInsertXmlUtil.getNode("/POOR_HIP1008/controlActProcess/subject/recordTarget/patientRole/id[@root='2.16.156.10011.1.24']/@extension");
        String eafNo = eafNoNode.getNodeValue();
        String serialnum = reportFlag + "@" + eafNo;

//        Node assortIdNode = inspectionInsertXmlUtil.getNode("/POOR_HIP1008/controlActProcess/subject/component/structuredBody/component[@displayName='检查报告']/section/entry[@displayName='检查类型']/observation/code/@displayName");
//        String assortId = assortIdNode.getNodeValue();

//        Node sysFlagNode = inspectionInsertXmlUtil.getNode("/POOR_HIP1008/controlActProcess/subject/component/structuredBody/component[@displayName='检查报告']/section/entry[@displayName='检查类型']/observation/code/@displayName");
//        String sysFlag = sysFlagNode.getNodeValue();

        Node fileTitleNode = inspectionInsertXmlUtil.getNode("/POOR_HIP1008/controlActProcess/subject/component/structuredBody/component[@displayName='检查结果明细']/section/entry[@displayName='检查项目']/organizer/component[@displayName='检查项目']/observation/value");
        String fileTitle = fileTitleNode.getTextContent();

        Node downUrlNode = inspectionInsertXmlUtil.getNode("/POOR_HIP1008/controlActProcess/subject/component/structuredBody/component[@displayName='检查报告图像']/report/entry[@displayName='检查报告图像URL地址']/observation/value");
        String downUrl = downUrlNode.getTextContent();

        ReportDto reportDto = new ReportDto();
        reportDto.setReportSn(reportFlag);
        reportDto.setAdmisstimes(admissTimes);
        reportDto.setInpatientNo(inpatientNo);
        reportDto.setSerialnum(serialnum);
        reportDto.setFileTitle(fileTitle);
        reportDto.setDownUrl(downUrl);
        reportDto.setAssortId(zdAssortId);
        reportDto.setSysFlag(sender);
        reportDto.setFileSource("1");
        reportDto.setFilestoragetype("1");
        return reportDto;
    }

    /**
     * 返回检查报告新增成功消息
     *
     * @param msgId    消息id
     * @param sender   发送路由
     * @param receiver 接收路由
     * @return 新增成功消息响应
     */
    public String insertSuccess(String msgId, String sender, String receiver) {
        String createTime = Func.format(new Date(), DateUtil.PATTERN_DATETIME_MINI);
        return "<MCCI_IN000002UV01 xmlns=\"urn:hl7-org:v3\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ITSVersion=\"XML_1.0\" xsi:schemaLocation=\"urn:hl7-org:v3  file:///E:/hl7/HL7/v3ballot_fullsite_2011MAY/v3ballot/html/processable/multicacheschemas/MCCI _IN000002UV01.xsd\">" +
                "<id extension=\"" + IdUtil.standardUUID() + "\"/>" +
                "<creationTime value=\"" + createTime + "\"/>" +
                "<interactionId root=\"2.16.840.1.113883.1.6\" extension=\"MCCI_IN000002UV01\"/>" +
                "<processingCode code=\"P\"/>" +
                "<processingModeCode/>" +
                "<acceptAckCode code=\"AL\"/>" +
                "<receiver typeCode=\"RCV\">" +
                "<device classCode=\"DEV\" determinerCode=\"INSTANCE\">" +
                "<id>" +
                "<item extension=\"Orion-001\"/>" +
                "</id>" +
                "</device>" +
                "</receiver>" +
                "<sender typeCode=\"SND\">" +
                "<device classCode=\"DEV\" determinerCode=\"INSTANCE\">" +
                "<id>" +
                "<item extension=\"PaperlessManagementMRIS-001\"/>" +
                "</id>" +
                "</device>" +
                "</sender>" +
                "<acknowledgement typeCode=\"AA\">" +
                "<targetMessage>" +
                "<id extension=\"" + msgId + "\"/>" +
                "</targetMessage>" +
                "<acknowledgementDetail>" +
                "<text value=\"成功\"/>" +
                "</acknowledgementDetail>" +
                "</acknowledgement>" +
                "</MCCI_IN000002UV01>";
//        return "<MCCI_IN000002UV01 ITSVersion=\"XML_1.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"urn:hl7-org:v3 ../multicacheschemas/MCCI_IN000002UV01.xsd\" xmlns=\"urn:hl7-org:v3\">" +
//                "<id root=\"2.16.156.10011.0\" extension=\"" + IdUtil.standardUUID() + "\"/>" +
//                "<creationTime value=\"" + createTime + "\"/>" +
//                "<interactionId root=\"2.16.840.1.113883.1.6\" extension=\"MCCI_IN000002UV01\" displayable=\"true\"/>" +
//                "<processingCode code=\"P\"/>" +
//                "<processingModeCode/>" +
//                "<acceptAckCode code=\"AL\"/>" +
//                "<receiver typeCode=\"RCV\">" +
//                "<device classCode=\"DEV\" determinerCode=\"INSTANCE\">" +
//                "<id>" +
//                "<item root=\"2.16.156.10011.0.1.1\" extension=\"2.16.156.10011.0.1.1\"/>" +
//                "</id>" +
//                "</device>" +
//                "</receiver>" +
//                "<sender typeCode=\"SND\">" +
//                "<device classCode=\"DEV\" determinerCode=\"INSTANCE\">" +
//                "<id>" +
//                "<item root=\"2.16.156.10011.0.1.2\" extension=\"2.16.156.10011.0.1.2\"/>" +
//                "</id>" +
//                "</device>" +
//                "</sender>" +
//                "<acknowledgement typeCode=\"AA\">" +
//                "<targetMessage>" +
//                "<id root=\"2.16.156.10011.0\" extension=\"" + msgId + "\"/>" +
//                "</targetMessage>" +
//                "<acknowledgementDetail typeCode=\"I\">" +
//                "      <text value=\"成功！\"/> " +
//                "</acknowledgementDetail>" +
//                "</acknowledgement>" +
//                "</MCCI_IN000002UV01>";
    }

    /**
     * 返回检查报告插入失败响应消息
     *
     * @param msgId    消息id
     * @param sender   发送路由
     * @param receiver 接收路由
     * @return 检查报告新增失败响应消息
     */
    public String insertFailed(String msgId, String sender, String receiver, String failedMessage) {

        String createTime = Func.format(new Date(), DateUtil.PATTERN_DATETIME_MINI);
        return "<MCCI_IN000002UV01 xmlns=\"urn:hl7-org:v3\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ITSVersion=\"XML_1.0\" xsi:schemaLocation=\"urn:hl7-org:v3  file:///E:/hl7/HL7/v3ballot_fullsite_2011MAY/v3ballot/html/processable/multicacheschemas/MCCI _IN000002UV01.xsd\">" +
                "<id extension=\"" + IdUtil.standardUUID() + "\"/>" +
                "<creationTime value=\"" + createTime + "\"/>" +
                "<interactionId root=\"2.16.840.1.113883.1.6\" extension=\"MCCI_IN000002UV01\"/>" +
                "<processingCode code=\"P\"/>" +
                "<processingModeCode/>" +
                "<acceptAckCode code=\"AL\"/>" +
                "<receiver typeCode=\"RCV\">" +
                "<device classCode=\"DEV\" determinerCode=\"INSTANCE\">" +
                "<id>" +
                "<item extension=\"Orion-001\"/>" +
                "</id>" +
                "</device>" +
                "</receiver>" +
                "<sender typeCode=\"SND\">" +
                "<device classCode=\"DEV\" determinerCode=\"INSTANCE\">" +
                "<id>" +
                "<item extension=\"PaperlessManagementMRIS-001\"/>" +
                "</id>" +
                "</device>" +
                "</sender>" +
                "<acknowledgement typeCode=\"AE\">" +
                "<targetMessage>" +
                "<id extension=\"" + msgId + "\"/>" +
                "</targetMessage>" +
                "<acknowledgementDetail>" +
                "<text value=\"" + failedMessage + "\"/>" +
                "</acknowledgementDetail>" +
                "</acknowledgement>" +
                "</MCCI_IN000002UV01>";
//        return "<MCCI_IN000002UV01 ITSVersion=\"XML_1.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"urn:hl7-org:v3 ../multicacheschemas/MCCI_IN000002UV01.xsd\" xmlns=\"urn:hl7-org:v3\">" +
//                "<id root=\"2.16.156.10011.0\" extension=\"" + IdUtil.standardUUID() + "\"/>" +
//                "<creationTime value=\"" + createTime + "\"/>" +
//                "<interactionId root=\"2.16.840.1.113883.1.6\" extension=\"MCCI_IN000002UV01\" displayable=\"true\"/>" +
//                "<processingCode code=\"P\"/>" +
//                "<processingModeCode/>" +
//                "<acceptAckCode code=\"AL\"/>" +
//                "<receiver typeCode=\"RCV\">" +
//                "<device classCode=\"DEV\" determinerCode=\"INSTANCE\">" +
//                "<id>" +
//                "<item root=\"2.16.156.10011.0.1.1\" extension=\"" + receiver + "\"/>" +
//                "</id>" +
//                "</device>" +
//                "</receiver>" +
//                "<sender typeCode=\"SND\">" +
//                "<device classCode=\"DEV\" determinerCode=\"INSTANCE\">" +
//                "<id>" +
//                "<item root=\"2.16.156.10011.0.1.2\" extension=\"" + sender + "\"/>" +
//                "</id>" +
//                "</device>" +
//                "</sender>" +
//                "<acknowledgement typeCode=\"AE\">" +
//                "<targetMessage>" +
//                "<id root=\"2.16.156.10011.0\" extension=\"" + msgId + "\"/>" +
//                "</targetMessage>" +
//                "<acknowledgementDetail typeCode=\"I\">" +
//                "      <text value=\""+failedMessage+"\"/> " +
//                "</acknowledgementDetail>" +
//                "</acknowledgement>" +
//                "</MCCI_IN000002UV01>";
    }


}
