package com.lantone.qc.trans.changx;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.lantone.qc.dbanaly.facade.changx.CxXmlUtil;
import com.lantone.qc.dbanaly.lt.facade.ModelHospitalFacade;
import com.lantone.qc.dbanaly.util.KernelConstants;
import com.lantone.qc.dbanaly.util.SpecialStorageUtil;
import com.lantone.qc.pub.model.doc.ThreeLevelWardDoc;
import com.lantone.qc.pub.model.doc.operation.OperationDoc;
import com.lantone.qc.pub.model.doc.operation.OperationRecordDoc;
import com.lantone.qc.pub.model.doc.ward.AttendingDoctorWardDoc;
import com.lantone.qc.pub.model.doc.ward.DirectorDoctorWardDoc;
import com.lantone.qc.pub.model.doc.ward.GeneralDoctorWardDoc;
import com.lantone.qc.pub.model.vo.MedrecVo;
import com.lantone.qc.pub.util.SpringContextUtil;
import com.lantone.qc.pub.util.StringUtil;
import com.lantone.qc.trans.ModelDocTrans;
import com.lantone.qc.trans.comsis.OrdinaryAssistant;
import com.lantone.qc.trans.comsis.Preproc;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Description: 查房记录文档生成
 * @author: rengb
 * @time: 2020/3/17 13:27
 */
@Setter
public class ChangxThreeLevelWardDocTrans extends ModelDocTrans {

    private List<String> recTitles;
    private List<OperationDoc> operationDocs;

    @Override
    public List<ThreeLevelWardDoc> extract(MedrecVo medrecVo) {
        ModelHospitalFacade modelHospitalFacade = SpringContextUtil.getBean(ModelHospitalFacade.class);
        recTitles = modelHospitalFacade.getRecTitles(1l, 4l);

        List<ThreeLevelWardDoc> retList = Lists.newArrayList();
        ThreeLevelWardDoc threeLevelWardDoc = new ThreeLevelWardDoc();
        List<Map<String, Object>> contentMaps = (List) medrecVo.getContent().get("content");
        contentMaps.forEach(contentMap -> {
            classifyThreeLevelWardDoc(threeLevelWardDoc, contentMap);
        });
        retList.add(threeLevelWardDoc);
        return retList;
    }

    private void classifyThreeLevelWardDoc(ThreeLevelWardDoc threeLevelWardDoc, Map<String, Object> contentMap) {
        String content = contentMap.get("xmlText").toString();
        Map<String, String> xmlNodeValueMap = CxXmlUtil.firstLevelNodeValue(content);
        xmlNodeValueMap.put("mode_id=" + contentMap.get("modeId").toString(), "");
        String recTitle = contentMap.get("recTitle").toString();
        if (recTitles.contains(recTitle)) {
            xmlNodeValueMap.put("rec_title=" + contentMap.get("recTitle").toString(), "");
        }
        Map<String, String> structureMap = OrdinaryAssistant.mapKeyContrast(xmlNodeValueMap, keyContrasts);
        structureMap.put("查房日期", structureMap.get("记录时间"));

        Map<String, String> cutWordMap = Maps.newHashMap();
        String text = CxXmlUtil.getXmlText(content);
        if (StringUtil.isNotBlank(text)) {
            if (StringUtil.isBlank(structureMap.get("病情记录"))) {
                structureMap.put("病情记录", text);
            }
            cutWordMap = Preproc.getCutWordMap(true, sourceTitles, text);
            if (StringUtil.isBlank(structureMap.get("记录医师"))) {
                Pattern p = Pattern.compile("^[^\\u4e00-\\u9fa5]+$");//分词结果如果不包含中文为日期，则不覆盖
                if (StringUtil.isNotEmpty(cutWordMap.get("医师签名"))) {
                    Matcher m = p.matcher(cutWordMap.get("医师签名"));
                    if (!m.matches()) {
                        structureMap.put("记录医师", cutWordMap.get("医师签名"));
                    }
                }
                if (StringUtil.isNotEmpty(cutWordMap.get("记录医生"))) {
                    Matcher m = p.matcher(cutWordMap.get("记录医生"));
                    if (!m.matches()) {
                        structureMap.put("记录医师", cutWordMap.get("记录医生"));
                    }
                }
            }
        }

        //总的查房记录 汇总
        ThreeLevelWardDoc allDoctorWradDoc = new ThreeLevelWardDoc();
        allDoctorWradDoc.setStructureMap(structureMap);
        allDoctorWradDoc.setPageData((Map) structureMap);
        threeLevelWardDoc.addAllDoctorWradDoc(allDoctorWradDoc);

        //主任医师查房
        DirectorDoctorWardDoc directorDoctorWardDoc = findDirectorDoctorWardDoc(structureMap);
        if (directorDoctorWardDoc != null) {
            threeLevelWardDoc.addDirectorDoctorWardDoc(findDirectorDoctorWardDoc(structureMap));
        }
        //主治医师查房
        AttendingDoctorWardDoc attendingDoctorWardDoc = findAttendingDoctorWardDoc(structureMap);
        if (attendingDoctorWardDoc != null) {
            threeLevelWardDoc.addAttendingDoctorWardDoc(attendingDoctorWardDoc);
        }
        //普通医师查房
        if (directorDoctorWardDoc == null && attendingDoctorWardDoc == null) {
            GeneralDoctorWardDoc generalDoctorWardDoc = new GeneralDoctorWardDoc();
            generalDoctorWardDoc.setStructureMap(structureMap);
            generalDoctorWardDoc.setPageData((Map) structureMap);
            threeLevelWardDoc.addGeneralDoctorWardDoc(generalDoctorWardDoc);
        }
    }

    /**
     * 主任医师查房
     *
     * @param structureMap
     */
    private DirectorDoctorWardDoc findDirectorDoctorWardDoc(Map<String, String> structureMap) {
        String title = structureMap.get("查房标题");
        String content = structureMap.get("病情记录");
        String recordDateStr = structureMap.get("查房日期");
        Date recordDate = StringUtil.parseDateTime(recordDateStr);
        //标题有代字
        DirectorDoctorWardDoc directorDoctorWardDoc = null;
        if (StringUtil.isNotBlank(title)) {
            if (title.contains("主刀")) {
                String doctorTitle = getDoctorTitle(operationDocs, recordDate, "主刀医师");
                title = title.replace("主刀", doctorTitle);
            } else if (title.contains("一助")) {
                String doctorTitle = getDoctorTitle(operationDocs, recordDate, "一助");
                title = title.replace("一助", doctorTitle);
            }
            if ((StringUtils.isNotEmpty(subTitle(title)) && subTitle(title).contains("主任")) || findDirector(title, content)) {
                directorDoctorWardDoc = new DirectorDoctorWardDoc();
                directorDoctorWardDoc.setStructureMap(structureMap);
                directorDoctorWardDoc.setPageData((Map) structureMap);
            }
        }
        return directorDoctorWardDoc;
    }

    /**
     * 主治医师查房
     *
     * @param structureMap
     */
    private AttendingDoctorWardDoc findAttendingDoctorWardDoc(Map<String, String> structureMap) {
        String title = structureMap.get("查房标题");
        String content = structureMap.get("病情记录");
        String recordDateStr = structureMap.get("查房日期");
        Date recordDate = StringUtil.parseDateTime(recordDateStr);
        AttendingDoctorWardDoc attendingDoctorWardDoc = null;
        //标题有代字
        if (StringUtil.isNotBlank(title)) {
            if (title.contains("主刀")) {
                String doctorTitle = getDoctorTitle(operationDocs, recordDate, "主刀医师");
                title = title.replace("主刀", doctorTitle);
            } else if (title.contains("一助")) {
                String doctorTitle = getDoctorTitle(operationDocs, recordDate, "一助");
                title = title.replace("一助", doctorTitle);
            }
            if ((StringUtils.isNotEmpty(subTitle(title)) && subTitle(title).contains("主治"))
                    || findAttend(title, content)) {
                attendingDoctorWardDoc = new AttendingDoctorWardDoc();
                attendingDoctorWardDoc.setStructureMap(structureMap);
                attendingDoctorWardDoc.setPageData((Map) structureMap);
            }
        }
        return attendingDoctorWardDoc;
    }

    /**
     * 共同照护讨论记录中找主任查房
     *
     * @param title
     * @param content
     * @return
     */
    private boolean findDirector(String title, String content) {
        return title.contains("共同照护讨论记录") && content.contains("主任");
    }

    /**
     * 共同照护讨论记录中找主治查房
     *
     * @param title
     * @param content
     * @return
     */
    private boolean findAttend(String title, String content) {
        return title.contains("共同照护讨论记录") && content.contains("主治");
    }

    private String subTitle(String srcText) {
        if (StringUtil.isNotBlank(srcText) && srcText.contains("代") && srcText.indexOf("代") != srcText.length() - 1) {
            srcText = srcText.substring(srcText.lastIndexOf("代") + 1);
        }
        return srcText;
    }

    private List<String> sourceTitles = Lists.newArrayList(
            "医师签名",
            "记录医生"
    );

    private List<String> keyContrasts = Lists.newArrayList(
            "病程记录标题=查房标题",
            "在此输入查房记录=病情记录",
            "签名++++=记录医师",
            "在此输入副主任医师代主治医师查房记录++++文本框=病情记录",
            "日常病程记录++++文本框=病情记录",
            "在此输入副主任医师查房记录++++文本框=病情记录",
            "在此输入副主任兼主刀医师查房记录++++文本框=病情记录",
            "在此输入副主任医师代主治医师查房记录++++文本框=病情记录",
            "科主任=三级医师",
            "入院诊断++++初步诊断=入院诊断",
            "记录日期=记录时间"
    );

    /**
     * 获取主刀医师/一助职称(取距离查房记录时间最近的一次手术记录)
     *
     * @param operationDocs
     * @return
     */
    public static String getDoctorTitle(List<OperationDoc> operationDocs, Date recordDate, String findTitle) {
        String title = "";
        SpecialStorageUtil specialStorageUtil = SpringContextUtil.getBean("specialStorageUtil");
        Map<String, Object> surgeon = specialStorageUtil.getJsonStringValue(KernelConstants.HOSPITAL_DOCTOR_MAP);
        if (surgeon == null) {
            return title;
        }
        /* 用于存放手术结束时间距离查房时间最近的一次时间差 */
        long timeDiff = 0L;
        for (OperationDoc operationDoc : operationDocs) {
            OperationRecordDoc operationRecordDoc = operationDoc.getOperationRecordDoc();
            if (operationRecordDoc == null) {
                continue;
            }
            Map<String, String> structureMap = operationRecordDoc.getStructureMap();
            String chiefSurgeon = structureMap.get(findTitle);
            String operatorEndDateStr = structureMap.get("手术结束时间");

            if (StringUtil.isBlank(chiefSurgeon) || StringUtil.isBlank(operatorEndDateStr)) {
                continue;
            }
            Map<String, String> doctor = (Map) surgeon.get(chiefSurgeon);
            if (doctor != null) {
                String professor = doctor.get("professor");
                Date operatorEndDate = StringUtil.parseDateTime(operatorEndDateStr);
                if (operatorEndDate != null) {
                    long timeDifference = timeDifference(operatorEndDate, recordDate);
                    if (timeDifference == 0){
                        continue;
                    }
                    if (timeDiff == 0 || timeDiff > timeDifference) {
                        /* 取距离此次主刀医师查房最近的一次手术时间 */
                        timeDiff = timeDifference;
                        title = professor;
                    }
                }
            }
        }
        return title;
    }

    public static long timeDifference(Date firstDate, Date secondDate) {
        long timeDifference = 0L;
        if (firstDate == null || secondDate == null) {
            return timeDifference;
        }
        boolean flag = false;
        if (firstDate.before(secondDate)) {
            flag = true;
        }
        Calendar calendarS = Calendar.getInstance();
        Calendar calendarE = Calendar.getInstance();
        long timeS, timeE;
        try {
            calendarS.setTime(firstDate);
            calendarE.setTime(secondDate);

            timeS = calendarS.getTimeInMillis();
            timeE = calendarE.getTimeInMillis();

            if (flag) {
                timeDifference = (timeE - timeS) / (1000 * 60);
            } else {
                timeDifference = (timeS - timeE) / (1000 * 60);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return timeDifference;
    }

}