package com.lantone.structure.ai;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.lantone.structure.client.CRFServiceClient;
import com.lantone.structure.ai.process.EntityProcessThreeLevelWard;
import com.lantone.common.util.CatalogueUtil;
import com.lantone.structure.model.Content;
import com.lantone.structure.model.InputInfo;
import com.lantone.structure.model.doc.DifficultCaseDiscussDoc;
import com.lantone.structure.model.doc.RescueDoc;
import com.lantone.structure.model.doc.ThreeLevelWardDoc;
import com.lantone.structure.model.doc.WardRecordDoc;
import com.lantone.structure.model.doc.ward.AttendingDoctorWardDoc;
import com.lantone.structure.model.doc.ward.DirectorDoctorWardDoc;
import com.lantone.structure.model.label.ThreeLevelWardLabel;
import com.lantone.common.util.ListUtil;
import com.lantone.common.util.StringUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @ClassName : ThreeLevelWardAI
 * @Description :
 * @Author : 胡敬
 * @Date: 2020-03-23 09:52
 */
public class ThreeLevelWardAI extends ModelAI {
    /**
     *
     */
    public static List<String> medicalTextType = Arrays.asList("CourseRecord_cx", "CourseRecordLast_cx", "CourseRecordSRR","Taizhou_medical_order");
    public static String entityRelationObject = "entity_relation_object";
    public static String outputs = "outputs";
    public static String content = "content";

    public void medrec(InputInfo inputInfo, CRFServiceClient crfServiceClient) {
        JSONArray crfContent = new JSONArray();
        List<ThreeLevelWardDoc> threeLevelWardDocs = inputInfo.getThreeLevelWardDocs();
        //  "============恩泽医嘱crf单独处理================="
        if (ListUtil.isNotEmpty(threeLevelWardDocs) && StringUtil.isNotEmpty(threeLevelWardDocs.get(0).getText())) {
            Map<String, String> maps = threeLevelWardDocs.get(0).getStructureMap();
            String plan = inputInfo.getThreeLevelWardDocs().get(0).getText();
            if(StringUtil.isNotEmpty(maps.get("诊疗计划")) && StringUtil.isNotEmpty(maps.get("诊疗计划").trim())){
                plan = maps.get("诊疗计划");
            }
                putContent(crfContent, medicalTextType.get(3), plan, Content.wardRecord);
            JSONObject midData = loadAI(crfContent, crfServiceClient);//crf返回数据
            for (int i = 0; i < threeLevelWardDocs.size(); i++) {
                if (midData.get(Content.wardRecord) == null) {
                    continue;
                }
                putRescueCrfData(midData.getJSONObject(Content.wardRecord), inputInfo);
            }
    }
        //  "============恩泽医嘱crf单独处理完成================="

        if (threeLevelWardDocs.size() == 0) {
            return;
        }
        ThreeLevelWardDoc threeLevelWardDoc = threeLevelWardDocs.get(0);
        List<AttendingDoctorWardDoc> attendingDocs = threeLevelWardDoc.getAttendingDoctorWardDocs();//主治医师查房记录
        if (attendingDocs.size() > 0) {
            //主治医师首次查房记录
            Map<String, String> fitstAttStructureMap = attendingDocs.get(0).getStructureMap();
            putContent(crfContent, medicalTextType.get(0), fitstAttStructureMap.get("病情记录"), Content.attend);
        }

        List<DirectorDoctorWardDoc> directorDocs = threeLevelWardDoc.getDirectorDoctorWardDocs();//主任医师查房记录
        if (directorDocs.size() > 0) {
            //主任医师首次查房记录
            Map<String, String> fitstDirStructureMap = directorDocs.get(0).getStructureMap();
            putContent(crfContent, medicalTextType.get(0), fitstDirStructureMap.get("病情记录"), Content.director);

            //主任医师最后一次查房记录
            Map<String, String> lastDirStructureMap = directorDocs.get(directorDocs.size() - 1).getStructureMap();
            putContent(crfContent, medicalTextType.get(0), lastDirStructureMap.get("病情记录"), Content.director + "最后一次");
        }

        //所有查房记录,2020/08/20新增所有查房记录抽取：实验室检查、辅助检查、药品等
        List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDoc.getAllDoctorWradDocs();
        if (allDoctorWradDocs.size() > 0) {
            Map<String, String> lastWardStructureMap = allDoctorWradDocs.get(allDoctorWradDocs.size() - 1).getStructureMap();
            putContent(crfContent, medicalTextType.get(1), lastWardStructureMap.get("病情记录"), "末次查房");
            //2020/08/20新增所有查房记录抽取：实验室检查、辅助检查、药品等
            for (int i = 0; i < allDoctorWradDocs.size(); i++) {
                Map<String, String> structureMap = allDoctorWradDocs.get(i).getStructureMap();
                String content = CatalogueUtil.structureMapJoin(structureMap, Lists.newArrayList("体检", "病情记录", "治疗计划和措施"));
                putContent(crfContent, medicalTextType.get(2), content, "第" + i + "次查房");
            }

        }

        List<Map<String, String>> directorDifficultRecord = new ArrayList<>();
        //疑难患者副高及以上查房记录
        if (inputInfo.getDifficultCaseDiscussDocs().size() > 0) {
            directorDifficultRecord = putDirectorDifficultRecord(inputInfo, allDoctorWradDocs);
            for (int i = 0; i < directorDifficultRecord.size(); i++) {
                putContent(crfContent, medicalTextType.get(0), directorDifficultRecord.get(i).get("病情记录"), Content.difficultPatients + i, directorDifficultRecord.get(i).get("查房日期"));
            }
        }
        List<Map<String, String>> directorRescueRecord = new ArrayList<>();
        //抢救患者副高及以上查房记录
        if (inputInfo.getRescueDocs().size() > 0) {
            directorRescueRecord = putDirectorRescueRecord(inputInfo, allDoctorWradDocs);
            for (int i = 0; i < directorRescueRecord.size(); i++) {
                putContent(crfContent, medicalTextType.get(0), directorRescueRecord.get(i).get("病情记录"), Content.rescuingPatients + i, directorRescueRecord.get(i).get("查房日期"));
            }
        }

        JSONObject midData = loadAI(crfContent, crfServiceClient);//crf返回数据

        //主治医师首次查房记录模型输出
        if (midData.get(Content.attend) != null) {
            attendingDocs.get(0).setThreeLevelWardLabel(putWardRoundCrfData(midData.getJSONObject(Content.attend)));
        }
        //主任医师首次查房记录模型输出
        if (midData.get(Content.director) != null) {
            directorDocs.get(0).setThreeLevelWardLabel(putWardRoundCrfData(midData.getJSONObject(Content.director)));
        }
        //主任医师最后一次查房记录模型输出
        if (midData.get(Content.director + "最后一次") != null) {
            directorDocs.get(directorDocs.size() - 1).setThreeLevelWardLabel(putWardRoundCrfData(midData.getJSONObject(Content.director + "最后一次")));
        }
        //最后一次查房记录模型输出
        if (midData.get("末次查房") != null) {
            allDoctorWradDocs.get(allDoctorWradDocs.size() - 1).setThreeLevelWardLabel(Lists.newArrayList(putWardRoundCrfData(midData.getJSONObject("末次查房"))));
        }
        //疑难患者副高及以上查房记录模型输出
        if (inputInfo.getDifficultCaseDiscussDocs().size() > 0 && ListUtil.isNotEmpty(directorDifficultRecord)) {
            for (int i = 0; i < directorDifficultRecord.size(); i++) {
                if (midData.get(Content.difficultPatients + i) == null) {
                    continue;
                }
                putWardRoundCrfData(midData.getJSONObject(Content.difficultPatients + i), inputInfo, 2);//查房记录
            }
        }
        //抢救患者副高及以上查房记录模型输出
        if (inputInfo.getRescueDocs().size() > 0 && ListUtil.isNotEmpty(directorDifficultRecord)) {
            for (int i = 0; i < directorDifficultRecord.size(); i++) {
                if (midData.get(Content.rescuingPatients + i) == null) {
                    continue;
                }
                putWardRoundCrfData(midData.getJSONObject(Content.rescuingPatients + i), inputInfo, 3);//查房记录
            }
        }

        //2020/08/20新增所有查房记录抽取：实验室检查、辅助检查、药品等
        for (int i = 0; i < allDoctorWradDocs.size(); i++) {
            if (midData.get("第" + i + "次查房") == null) {
                continue;
            }
            putWardRoundCrfData(midData.getJSONObject("第" + i + "次查房"), inputInfo, 0);//查房记录
        }

    }

    /**
     * 处理查房记录
     *
     * @param jsonObject
     */
    public void putRescueCrfData(JSONObject jsonObject, InputInfo inputInfo) {
        if (jsonObject == null) {
            return;
        }
        JSONObject aiOut = jsonObject.getJSONObject(entityRelationObject).getJSONObject(ThreeLevelWardAI.outputs);
        if (aiOut == null) {
            return;
        }
        EntityProcessThreeLevelWard entityProcessThreeLevelWard = new EntityProcessThreeLevelWard();
        ThreeLevelWardLabel threeLevelWardLabel = entityProcessThreeLevelWard.extractEntityLate(aiOut);
        List<ThreeLevelWardLabel> threeLevelWardLabels = new ArrayList<>();
        threeLevelWardLabels.add(threeLevelWardLabel);
        inputInfo.getThreeLevelWardDocs().get(0).setThreeLevelWardLabel(threeLevelWardLabels);
    }

    protected void putContent(JSONArray crfContent, String medicalTextType, String text, String sign, String wardDate) {
        String moveText = CatalogueUtil.removeSpecialChar(text);
        if (StringUtil.isEmpty(moveText)) {
            return;
        }
        JSONObject detailContent = new JSONObject();
        detailContent.put("medical_text_type", medicalTextType);
        detailContent.put("content", moveText);
        detailContent.put("detail_title", sign);
        detailContent.put("wardDate", wardDate);
        crfContent.add(detailContent);
    }

    /**
     * 处理全部查房记录
     *
     * @param jsonObject
     * @param inputInfo
     */
    public void putWardRoundCrfData(JSONObject jsonObject, InputInfo inputInfo, int serious) {
        JSONObject aiOut = loadEntity(jsonObject, entityRelationObject, outputs, content);
        if (aiOut == null) {
            return;
        }
        String wardDate = jsonObject.getString("wardDate");
        String detailTitle = jsonObject.getString("detail_title");
        EntityProcessThreeLevelWard entityProcessThreeLevelWard = new EntityProcessThreeLevelWard();
        ThreeLevelWardLabel threeLevelWardLabel = entityProcessThreeLevelWard.extractEntity(aiOut);
        threeLevelWardLabel.setTitle(detailTitle);
        threeLevelWardLabel.setSerious(serious);
        ThreeLevelWardDoc threeLevelWardDoc = inputInfo.getThreeLevelWardDocs().get(0);
        //2020/08/20新增所有查房记录抽取：实验室检查、辅助检查、药品等
        Pattern p = Pattern.compile("\\d+");
        Matcher matcher = p.matcher(detailTitle);
        if (matcher.find()) {
            String num = matcher.group(0);
            int n = Integer.parseInt(num);
            ThreeLevelWardDoc doc = threeLevelWardDoc.getAllDoctorWradDocs().get(n);
            if (doc.getThreeLevelWardLabel().size() > 0) {
                doc.getThreeLevelWardLabel().add(threeLevelWardLabel);
            } else {
                threeLevelWardDoc.getAllDoctorWradDocs().get(n).setThreeLevelWardLabel(Lists.newArrayList(threeLevelWardLabel));
            }
        }
        List<ThreeLevelWardDoc> allDoctorWradDocs = threeLevelWardDoc.getAllDoctorWradDocs();
        for (ThreeLevelWardDoc wardDoc : allDoctorWradDocs) {
            String date = wardDoc.getStructureMap().get("查房日期");
            if (StringUtil.isNotBlank(date) && StringUtil.isNotBlank(wardDate) && date.equals(wardDate)) {
                wardDoc.getThreeLevelWardLabel().add(threeLevelWardLabel);
                break;
            }
        }
    }

    /**
     * 处理主治主任首次、末次查房
     *
     * @param jsonObject
     * @return
     */
    public ThreeLevelWardLabel putWardRoundCrfData(JSONObject jsonObject) {
        JSONObject aiOut = loadEntity(jsonObject, entityRelationObject, outputs, content);
        if (aiOut == null) {
            return new ThreeLevelWardLabel();
        }
        String detailTitle = jsonObject.getString("detail_title");
        EntityProcessThreeLevelWard entityProcessThreeLevelWard = new EntityProcessThreeLevelWard();
        ThreeLevelWardLabel threeLevelWardLabel = entityProcessThreeLevelWard.extractEntity(aiOut);
        threeLevelWardLabel.setTitle(detailTitle);
        return entityProcessThreeLevelWard.extractEntity(aiOut);

    }

    /**
     * 存放每条疑难病例讨论记录后第一条查房记录
     *
     * @param inputInfo
     * @param allDoctorWradDocs
     * @return
     */
    public List<Map<String, String>> putDirectorDifficultRecord(InputInfo inputInfo, List<ThreeLevelWardDoc> allDoctorWradDocs) {
        List<Map<String, String>> record = new ArrayList<>();
        List<DifficultCaseDiscussDoc> difficultCaseDiscussDocs = inputInfo.getDifficultCaseDiscussDocs(); //疑难病例讨论记录
        Map<Date, Map<String, String>> dateRecord = new TreeMap<>(new Comparator<Date>() {
            @Override
            public int compare(Date o1, Date o2) {
                // 升序排列
                return o1.compareTo(o2);
            }
        });//按时间key排序，存放抢救记录、查房记录
        String recordTime = "", title = "";
        for (DifficultCaseDiscussDoc difficultCaseDiscussDoc : difficultCaseDiscussDocs) {
            Map<String, String> difficultCaseDiscussStructureMap = difficultCaseDiscussDoc.getStructureMap();
            recordTime = difficultCaseDiscussStructureMap.get("讨论日期");
            Date recordDate = null;
            if (StringUtil.isNotEmpty(recordTime)) {
                recordDate = StringUtil.parseDateTime(recordTime);
            }
            if (recordDate == null) {
                continue;
            }
            dateRecord.put(recordDate, difficultCaseDiscussStructureMap);
        }
        dateRecord = extractUnique(dateRecord);
        for (ThreeLevelWardDoc threeLevelWardDoc : allDoctorWradDocs) {
            Map<String, String> rescueStructureMap = threeLevelWardDoc.getStructureMap();
            recordTime = rescueStructureMap.get("查房日期");
            title = CatalogueUtil.subTitle(rescueStructureMap.get("查房标题"));
            Date recordDate = StringUtil.parseDateTime(recordTime);
            if (recordDate == null || StringUtil.isBlank(title) || !title.contains(Content.director)) {//只存副高以上查房记录) {
                continue;
            }
            dateRecord.put(recordDate, rescueStructureMap);
        }
        List<Map<String, String>> dateRecordList = new ArrayList<>(dateRecord.values());
        //如果最后一条是疑难病例讨论记录，则之后肯定没有查房记录
        if (dateRecordList.get(dateRecordList.size() - 1).containsKey("讨论日期")) {
            record = new ArrayList<>();
            return record;
        }
        for (int i = 0; i < dateRecordList.size(); i++) {
            if (i != dateRecordList.size() - 1) {
                //当前为疑难病例讨论记录
                if (!dateRecordList.get(i).containsKey("讨论日期")) {
                    continue;
                }
                //疑难病例讨论记录下一条不是查房记录则清空list
                if (!dateRecordList.get(i + 1).containsKey("查房日期")) {
                    record = new ArrayList<>();
                    break;
                } else {
                    //疑难病例讨论记录下一条是查房记录,添加进list(这条疑难病例讨论记录后全部查房记录的第一条)
                    record.add(dateRecordList.get(i + 1));
                }
            }
        }
        return record;
    }

    /**
     * 存放每条抢救记录后第一条
     *
     * @param inputInfo
     * @param allDoctorWradDocs
     * @return
     */
    public List<Map<String, String>> putDirectorRescueRecord(InputInfo inputInfo, List<ThreeLevelWardDoc> allDoctorWradDocs) {
        List<Map<String, String>> record = new ArrayList<>();
        List<RescueDoc> rescueDocs = inputInfo.getRescueDocs(); //抢救记录
        Map<Date, Map<String, String>> dateRecord = new TreeMap<>(new Comparator<Date>() {
            @Override
            public int compare(Date o1, Date o2) {
                // 升序排列
                return o1.compareTo(o2);
            }
        });//按时间key排序，存放抢救记录、查房记录
        String recordTime = "", title = "";
        for (RescueDoc rescueDoc : rescueDocs) {
            Map<String, String> rescueStructureMap = rescueDoc.getStructureMap();
            recordTime = rescueStructureMap.get("抢救结束时间");
            if (recordTime == null) {
                continue;
            }
            Date recordDate = StringUtil.parseDateTime(recordTime);
            if (recordDate == null) {
                continue;
            }
            dateRecord.put(recordDate, rescueStructureMap);
        }
        dateRecord = extractUnique(dateRecord);
        for (ThreeLevelWardDoc threeLevelWardDoc : allDoctorWradDocs) {
            Map<String, String> rescueStructureMap = threeLevelWardDoc.getStructureMap();
            recordTime = rescueStructureMap.get("查房日期");
            title = CatalogueUtil.subTitle(rescueStructureMap.get("查房标题"));
            Date recordDate = StringUtil.parseDateTime(recordTime);
            if (recordDate == null || StringUtil.isBlank(title) || !title.contains(Content.director)) {//只存副高以上查房记录) {
                continue;
            }
            dateRecord.put(recordDate, rescueStructureMap);
        }
        List<Map<String, String>> dateRecordList = new ArrayList<>(dateRecord.values());
        //如果最后一条是抢救记录，则之后肯定没有查房记录
        if (ListUtil.isNotEmpty(dateRecordList) && dateRecordList.get(dateRecordList.size() - 1).containsKey("抢救结束时间")) {
            record = new ArrayList<>();
            return record;
        }
        for (int i = 0; i < dateRecordList.size(); i++) {
            if (i != dateRecordList.size() - 1) {
                //当前为抢救记录
                if (!dateRecordList.get(i).containsKey("抢救结束时间")) {
                    continue;
                }
                //抢救记录下一条不是查房记录则清空list
                if (!dateRecordList.get(i + 1).containsKey("查房日期")) {
                    record = new ArrayList<>();
                    break;
                } else {
                    //抢救记录下一条是查房记录,添加进list(抢救记录后全部查房记录的第一条)
                    record.add(dateRecordList.get(i + 1));
                }
            }
        }
        return record;
    }

    /**
     * 抽取24小时内第一条记录
     *
     * @param dateRecord
     */
    private Map<Date, Map<String, String>> extractUnique(Map<Date, Map<String, String>> dateRecord) {
        Map<Date, Map<String, String>> record = new TreeMap<>(new Comparator<Date>() {
            @Override
            public int compare(Date o1, Date o2) {
                // 升序排列
                return o1.compareTo(o2);
            }
        });
        Date lastDate = null;
        for (Map.Entry<Date, Map<String, String>> dateRecordEntry : dateRecord.entrySet()) {
            Date date = dateRecordEntry.getKey();
            if (lastDate == null || CatalogueUtil.compareTime(lastDate, date, (long) (24 * 60))) {
                lastDate = date;
                record.put(date, dateRecordEntry.getValue());
            }
        }
        return record;
    }
}