package com.lantone.qc.trans.beilun;

import com.google.common.collect.Lists;
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.FastJsonUtils;
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.beilun.util.BeiLunHtmlAnalysis;
import com.lantone.qc.trans.beilun.util.BeiLunThreeLevelWardHtmlAnalysis;
import com.lantone.qc.trans.comsis.OrdinaryAssistant;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

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

    private List<OperationDoc> operationDocs;

    @Override
    public List<ThreeLevelWardDoc> extract(MedrecVo medrecVo) {
        List<ThreeLevelWardDoc> retList = Lists.newArrayList();
        ThreeLevelWardDoc threeLevelWardDoc = new ThreeLevelWardDoc();
        List<Map<String, Object>> contentMaps = (List) medrecVo.getContent().get("content");
        contentMaps.forEach(contentMap -> {
            try {
                classifyThreeLevelWardDoc(threeLevelWardDoc, contentMap);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        });
        retList.add(threeLevelWardDoc);
        return retList;
    }

    private void classifyThreeLevelWardDoc(ThreeLevelWardDoc threeLevelWardDoc, Map<String, Object> contentMap) {
        String content = contentMap.get("xmlText").toString();
        Map<String, String> structureMap = null;
        if (contentMap.get("isParsed") != null && "1".equals(contentMap.get("isParsed").toString())) {
            structureMap = (Map) FastJsonUtils.getJsonToMap(content);
        } else {
            String recTitle = contentMap.get("recTitle").toString();
            String recTypeId = contentMap.get("recTypeId").toString();
            BeiLunHtmlAnalysis beiLunHtmlAnalysis = new BeiLunThreeLevelWardHtmlAnalysis();
            Map<String, String> sourceMap = beiLunHtmlAnalysis.analysis(content, recTitle, recTypeId);
            if (MapUtils.isNotEmpty(sourceMap)) {
                structureMap = OrdinaryAssistant.mapKeyContrast(sourceMap, keyContrasts);
                structureMap.put("记录编号", contentMap.get("recId").toString());
                structureMap.put("病历号", contentMap.get("behospitalCode") == null ? null : contentMap.get("behospitalCode").toString());
            }
        }
        if (MapUtils.isEmpty(structureMap)) {
            return;
        }

        if (structureMap.containsKey("病情记录")) {
            structureMap.put("病情记录", structureMap.get("病情记录").replace(" ", ""));
        }
        //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 writTitle = structureMap.get("文书标题");
        String recordDateStr = structureMap.get("查房日期");
        Date recordDate = StringUtil.parseDateTime(recordDateStr);
        //标题有代字
        DirectorDoctorWardDoc directorDoctorWardDoc = null;
        if (StringUtil.isNotBlank(title)) {
            if (title.contains("主刀") || title.contains("术后第")) {
                String doctorTitle = getDoctorTitle(operationDocs, recordDate, "主刀医师");
                title = title.replace("主刀", doctorTitle).replace("术后第", doctorTitle);
            } else if (title.contains("一助")) {
                String doctorTitle = getDoctorTitle(operationDocs, recordDate, "一助");
                title = title.replace("一助", doctorTitle);
            }
            if ((StringUtils.isNotEmpty(subTitle(title)) && subTitle(title).contains("主任")) || findDirector(content)
                    || title.contains("三级") || endocrinologyTitle(title)) {
                directorDoctorWardDoc = new DirectorDoctorWardDoc();
                directorDoctorWardDoc.setStructureMap(structureMap);
                directorDoctorWardDoc.setPageData((Map) structureMap);
            }
        }

        if (StringUtil.isNotBlank(writTitle)) {
            if (writTitle.contains("主刀") || writTitle.contains("术后第")) {
                String doctorTitle = getDoctorTitle(operationDocs, recordDate, "主刀医师");
                writTitle = writTitle.replace("主刀", doctorTitle).replace("术后第", doctorTitle);
            } else if (writTitle.contains("一助")) {
                String doctorTitle = getDoctorTitle(operationDocs, recordDate, "一助");
                writTitle = writTitle.replace("一助", doctorTitle);
            }
            if ((StringUtils.isNotEmpty(subTitle(writTitle)) && subTitle(writTitle).contains("主任")) || findDirector(content)
                    || writTitle.contains("三级") || endocrinologyTitle(writTitle)) {
                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 writTitle = 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("主刀") || title.contains("术后第")) {
                String doctorTitle = getDoctorTitle(operationDocs, recordDate, "主刀医师");
                title = title.replace("主刀", doctorTitle).replace("术后第", doctorTitle);
            } else if (title.contains("一助")) {
                String doctorTitle = getDoctorTitle(operationDocs, recordDate, "一助");
                title = title.replace("一助", doctorTitle);
            }
            if ((StringUtils.isNotEmpty(subTitle(title)) && subTitle(title).contains("主治"))
                    || findAttend(content) || title.contains("三级") || endocrinologyTitle(title)) {
                attendingDoctorWardDoc = new AttendingDoctorWardDoc();
                attendingDoctorWardDoc.setStructureMap(structureMap);
                attendingDoctorWardDoc.setPageData((Map) structureMap);
            }
        }

        //文书标题和模板标题不一致
        if (StringUtil.isNotBlank(writTitle)) {
            if (writTitle.contains("主刀") || writTitle.contains("术后第")) {
                String doctorTitle = getDoctorTitle(operationDocs, recordDate, "主刀医师");
                writTitle = writTitle.replace("主刀", doctorTitle).replace("术后第", doctorTitle);
            } else if (writTitle.contains("一助")) {
                String doctorTitle = getDoctorTitle(operationDocs, recordDate, "一助");
                writTitle = writTitle.replace("一助", doctorTitle);
            }
            if ((StringUtils.isNotEmpty(subTitle(writTitle)) && subTitle(writTitle).contains("主治"))
                    || findAttend(content) || writTitle.contains("三级") || endocrinologyTitle(writTitle)) {
                attendingDoctorWardDoc = new AttendingDoctorWardDoc();
                attendingDoctorWardDoc.setStructureMap(structureMap);
                attendingDoctorWardDoc.setPageData((Map) structureMap);
            }
        }
        return attendingDoctorWardDoc;
    }

    /**
     * 北仑内分泌科主任主治处理
     *
     * @param title
     * @return
     */
    private boolean endocrinologyTitle(String title) {
        String regex = ".*主任.*主任.*主治.*";
        return title.matches(regex);
    }

    /**
     * 共同照护讨论记录中找主任查房
     *
     * @param content
     * @return
     */
    private boolean findDirector(String content) {
        String director = "";
        if (content.indexOf("，") != -1) {
            director = content.substring(0, content.indexOf("，"));
        }
        return director.contains("主任");
    }

    /**
     * 共同照护讨论记录中找主治查房
     *
     * @param content
     * @return
     */
    private boolean findAttend(String content) {
        String director = "";
        if (content.indexOf("，") != -1) {
            director = content.substring(0, content.indexOf("，"));
        }
        return director.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> 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)) {
                chiefSurgeon = structureMap.get("手术者及助手名称");
                if (StringUtil.isNotBlank(chiefSurgeon) && chiefSurgeon.contains("、")) {
                    chiefSurgeon = chiefSurgeon.split("、")[0].replace("主刀：", "");
                }
            }
            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;
    }

}