package com.lantone.qc.kernel.structure.ai;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lantone.qc.kernel.client.CRFServiceClient;
import com.lantone.qc.kernel.structure.ai.model.EntityEnum;
import com.lantone.qc.kernel.structure.ai.model.Lemma;
import com.lantone.qc.kernel.structure.ai.process.*;
import com.lantone.qc.kernel.util.CatalogueUtil;
import com.lantone.qc.pub.Content;
import com.lantone.qc.pub.model.InputInfo;
import com.lantone.qc.pub.model.doc.BeHospitalizedDoc;
import com.lantone.qc.pub.model.entity.*;
import com.lantone.qc.pub.model.label.*;
import com.lantone.qc.pub.model.vo.CRFVo;
import com.lantone.qc.pub.util.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @ClassName : InHospitalDoc
 * @Description :
 * @Author : 楼辉荣
 * @Date: 2020-03-03 18:58
 */
@Component
public class BeHospitalizedAI extends ModelAI {
    /**
     * FirstCourseRecord_cx[病历首程]
     * PastFamily_cx[既往史家族史]
     * PersonalHistory_cx[个人史(月经史、婚育史)]
     * HPIForCX_cx[主诉、现病史、专科检查]
     * GeneralVital_cx[一般体格检查]
     * chief_present[邵逸夫医院主诉]
     * Diagnoses_cx[诊断]
     * Present_cx[现病史]
     */
    public static List<String> medicalTextType = Arrays.asList("FirstCourseRecord_cx", "PastFamily_cx", "PersonalHistory_cx", "HPIForCX_cx",
            "GeneralVital_cx", "chief_present", "Diagnoses_cx", "Present_cx");
    public static String entityRelationObject = "entity_relation_object";
    public static String outputs = "outputs";

    public void medrec(InputInfo inputInfo, CRFServiceClient crfServiceClient) {
        JSONArray crfContent = new JSONArray();
        BeHospitalizedDoc beHospitalizedDoc = inputInfo.getBeHospitalizedDoc();
        if (beHospitalizedDoc != null) {
            String chief_text = beHospitalizedDoc.getChiefLabel().getText();
            String personal_text = beHospitalizedDoc.getPersonalLabel().getText();
            String family_text = beHospitalizedDoc.getFamilyLabel().getText();
            String past_text = beHospitalizedDoc.getPastLabel().getText();
            String present_text = beHospitalizedDoc.getPresentLabel().getText();
            String pacs_text = beHospitalizedDoc.getPacsLabel().getText();
            String initial_diag_text = beHospitalizedDoc.getInitialDiagLabel().getText();   //初步诊断
            String revised_diag_text = beHospitalizedDoc.getRevisedDiagLabel().getText();   //修正诊断
            String supple_diag_text = beHospitalizedDoc.getSuppleDiagLabel().getText();    //补充诊断
            //月经史
            String menstrual_text = beHospitalizedDoc.getMenstrualLabel().getText();
            //婚育史
            String marital_text = beHospitalizedDoc.getMaritalLabel().getText();
            //一般体格检查
            String vital_text = beHospitalizedDoc.getVitalLabel().getText();
            //专科体格检查
            String vitalSpecial_text = beHospitalizedDoc.getVitalLabelSpecial().getText();
            if (beHospitalizedDoc.getChiefLabel().isCrfLabel()) {
                putContent(crfContent, medicalTextType.get(3), chief_text, Content.chief);  //主诉
            }
            if (beHospitalizedDoc.getPresentLabel().isCrfLabel()) {
                putContent(crfContent, medicalTextType.get(7), present_text, Content.present);//现病史
            }
            if (beHospitalizedDoc.getVitalLabelSpecial().isCrfLabel()) {
                putContent(crfContent, medicalTextType.get(3), vitalSpecial_text, Content.special_exam);//专科检查
            }
            if (beHospitalizedDoc.getPastLabel().isCrfLabel()) {
                putContent(crfContent, medicalTextType.get(1), past_text, Content.past);//既往史
            }
            if (beHospitalizedDoc.getFamilyLabel().isCrfLabel()) {
                putContent(crfContent, medicalTextType.get(1), family_text, Content.family);//家族史
            }
            if (beHospitalizedDoc.getVitalLabel().isCrfLabel()) {
                putContent(crfContent, medicalTextType.get(4), vital_text, Content.phys_exam);//存放一般查体
            }
            if (beHospitalizedDoc.getPersonalLabel().isCrfLabel()) {
                putContent(crfContent, medicalTextType.get(2), personal_text, Content.personal);//个人史
            }
            //月经史
            String concatMenstrual = "";
            if (personal_text != null) {
                if (personal_text.length() > 30) {
                    concatMenstrual = personal_text.substring(personal_text.length() - 30);
                } else {
                    concatMenstrual = personal_text;
                }
            }
            if (beHospitalizedDoc.getMenstrualLabel().isCrfLabel()) {
                putContent(crfContent, medicalTextType.get(2), concatMenstrual, menstrual_text, Content.menses);//月经史
            }
            if (beHospitalizedDoc.getMaritalLabel().isCrfLabel()) {
                putContent(crfContent, medicalTextType.get(2), marital_text, Content.marriage);//婚育史
            }
            if (beHospitalizedDoc.getPacsLabel().isCrfLabel()) {
                putContent(crfContent, medicalTextType.get(3), pacs_text, Content.pacs);//辅助检查(暂用主诉现病史模型,之后会新训练单独模型再做修改)
            }
            if (beHospitalizedDoc.getInitialDiagLabel().isCrfLabel()) {
                putContent(crfContent, medicalTextType.get(6), initial_diag_text, Content.initial_diag);//初步诊断
            }
            if (StringUtils.isNotEmpty(revised_diag_text) && beHospitalizedDoc.getRevisedDiagLabel().isCrfLabel()) {
                //修正诊断
                putContent(crfContent, medicalTextType.get(6), revised_diag_text, Content.revised_diag);
            }
            if (StringUtils.isNotEmpty(supple_diag_text) && beHospitalizedDoc.getSuppleDiagLabel().isCrfLabel()) {
                //补充诊断
                putContent(crfContent, medicalTextType.get(6), supple_diag_text, Content.supple_diag);
            }
            JSONObject midData = loadAI(crfContent, crfServiceClient);
            //处理主诉
            if (beHospitalizedDoc.getChiefLabel().isCrfLabel()) {
                putChiefCrfData(midData.getJSONObject(Content.chief), inputInfo);
            }
            //处理现病史
            if (beHospitalizedDoc.getPresentLabel().isCrfLabel()) {
                putPresentCrfData(midData.getJSONObject(Content.present), inputInfo);
            }
            //处理既往史
            if (beHospitalizedDoc.getPastLabel().isCrfLabel()) {
                putPastCrfData(midData.getJSONObject(Content.past), inputInfo);
            }
            //处理个人史
            if (beHospitalizedDoc.getPersonalLabel().isCrfLabel()) {
                putPersonalCrfData(midData.getJSONObject(Content.personal), inputInfo);
            }
            //处理月经史
            if (beHospitalizedDoc.getMenstrualLabel().isCrfLabel()) {
                putMensesCrfData(midData.getJSONObject(Content.menses), inputInfo);
            }
            //处理家族史
            if (beHospitalizedDoc.getFamilyLabel().isCrfLabel()) {
                putFamilyCrfData(midData.getJSONObject(Content.family), inputInfo);
            }
            //处理婚育史
            if (beHospitalizedDoc.getMaritalLabel().isCrfLabel()) {
                putMaritalCrfData(midData.getJSONObject(Content.marriage), inputInfo);
            }
            //处理初步诊断
            if (beHospitalizedDoc.getInitialDiagLabel().isCrfLabel()) {
                putInitialDiagCrfData(midData.getJSONObject(Content.initial_diag), inputInfo);
            }
            if (StringUtils.isNotEmpty(revised_diag_text) && beHospitalizedDoc.getRevisedDiagLabel().isCrfLabel()) {
                //处理修正诊断
                putRevisedDiagCrfData(midData.getJSONObject(Content.revised_diag), inputInfo);
            }
            if (StringUtils.isNotEmpty(revised_diag_text) && beHospitalizedDoc.getSuppleDiagLabel().isCrfLabel()) {
                //处理补充诊断
                putSuppleDiagCrfData(midData.getJSONObject(Content.supple_diag), inputInfo);
            }
            //处理辅助检查
            if (beHospitalizedDoc.getPacsLabel().isCrfLabel()) {
                putPacsCrfData(midData.getJSONObject(Content.pacs), inputInfo);
            }
        }
    }

    public void putChiefCrfData(JSONObject jsonObject, InputInfo inputInfo) {
        if (jsonObject == null) {
            return;
        }
        JSONObject aiOut = jsonObject.getJSONObject(entityRelationObject).getJSONObject(BeHospitalizedAI.outputs);
        if (aiOut == null) {
            return;
        }
        //使用现病史结构
        EntityProcessClinic entityProcessClinic = new EntityProcessClinic();
        PresentLabel presentLabel = entityProcessClinic.extractEntity(aiOut);

        ChiefLabel chiefLabel = inputInfo.getBeHospitalizedDoc().getChiefLabel();
        chiefLabel.setClinicals(presentLabel.getClinicals());
        chiefLabel.setDiags(presentLabel.getDiags());
        chiefLabel.setPds(presentLabel.getPds());
    }

    public void putPresentCrfData(JSONObject jsonObject, InputInfo inputInfo) {
        if (jsonObject == null) {
            return;
        }
        JSONObject aiOut = jsonObject.getJSONObject(entityRelationObject).getJSONObject(BeHospitalizedAI.outputs);
        if (aiOut == null) {
            return;
        }
        //放置入inputinfo
        EntityProcessClinic entityProcessClinic = new EntityProcessClinic();
        PresentLabel presentLabel = entityProcessClinic.extractEntity(aiOut);
        presentLabel.setText(inputInfo.getBeHospitalizedDoc().getPresentLabel().getText());
        List<Lis> lis = loadLises(aiOut);
        presentLabel.setLises(lis);
        inputInfo.getBeHospitalizedDoc().setPresentLabel(presentLabel);
    }

    /**
     * 家族史
     *
     * @param jsonObject
     * @param inputInfo
     */
    public void putFamilyCrfData(JSONObject jsonObject, InputInfo inputInfo) {
        if (jsonObject == null) {
            return;
        }
        JSONObject aiOut = jsonObject.getJSONObject(entityRelationObject).getJSONObject(BeHospitalizedAI.outputs);
        if (aiOut == null) {
            return;
        }
        //家族史信息处理
        EntityProcessFamily entityProcess = new EntityProcessFamily();
        FamilyLabel familyLabel = entityProcess.extractEntity(aiOut);
        familyLabel.setText(inputInfo.getBeHospitalizedDoc().getFamilyLabel().getText());
        inputInfo.getBeHospitalizedDoc().setFamilyLabel(familyLabel);
    }

    /**
     * 婚育史
     *
     * @param jsonObject
     * @param inputInfo
     */
    public void putMaritalCrfData(JSONObject jsonObject, InputInfo inputInfo) {
        if (jsonObject == null) {
            return;
        }
        JSONObject aiOut = jsonObject.getJSONObject(entityRelationObject).getJSONObject(BeHospitalizedAI.outputs);
        if (aiOut == null) {
            return;
        }
        //家族史信息处理
        EntityProcessMarital entityProcess = new EntityProcessMarital();
        MaritalLabel maritalLabel = entityProcess.extractEntity(aiOut);
        maritalLabel.setText(inputInfo.getBeHospitalizedDoc().getMaritalLabel().getText());
        inputInfo.getBeHospitalizedDoc().setMaritalLabel(maritalLabel);
    }

    public void putPastCrfData(JSONObject jsonObject, InputInfo inputInfo) {
        if (jsonObject == null) {
            return;
        }
        JSONObject aiOut = jsonObject.getJSONObject(entityRelationObject).getJSONObject(BeHospitalizedAI.outputs);
        if (aiOut == null) {
            return;
        }
        //放置入inputinfo
        EntityProcessPast entityProcessPast = new EntityProcessPast();
        PastLabel pastLabel = entityProcessPast.extractEntity(aiOut);
        pastLabel.setText(inputInfo.getBeHospitalizedDoc().getPastLabel().getText());
        inputInfo.getBeHospitalizedDoc().setPastLabel(pastLabel);

    }

    /**
     * 个人史信息提取
     *
     * @param jsonObject
     * @param inputInfo
     */
    public void putPersonalCrfData(JSONObject jsonObject, InputInfo inputInfo) {
        if (jsonObject == null) {
            return;
        }
        JSONObject aiOut = jsonObject.getJSONObject(entityRelationObject).getJSONObject(BeHospitalizedAI.outputs);
        if (aiOut == null) {
            return;
        }
        //个人史信息提取
        EntityProcessPersonal entityProcessPersonal = new EntityProcessPersonal();
        PersonalLabel personalLabel = entityProcessPersonal.extractEntity(aiOut);
        personalLabel.setText(inputInfo.getBeHospitalizedDoc().getPersonalLabel().getText());
        inputInfo.getBeHospitalizedDoc().setPersonalLabel(personalLabel);
    }

    /**
     * 月经史信息提取
     *
     * @param jsonObject
     * @param inputInfo
     */
    public void putMensesCrfData(JSONObject jsonObject, InputInfo inputInfo) {
        if (jsonObject == null) {
            return;
        }
        JSONObject aiOut = jsonObject.getJSONObject(entityRelationObject).getJSONObject(BeHospitalizedAI.outputs);
        if (aiOut == null) {
            return;
        }
        //月经史信息处理
        EntityProcessMenses entityProcess = new EntityProcessMenses();
        MenstrualLabel menstrualLabel = entityProcess.extractEntity(aiOut);
        menstrualLabel.setText(inputInfo.getBeHospitalizedDoc().getMenstrualLabel().getText());
        inputInfo.getBeHospitalizedDoc().setMenstrualLabel(menstrualLabel);
    }

    /**
     * 初步诊断信息提取
     *
     * @param jsonObject
     * @param inputInfo
     */
    public void putInitialDiagCrfData(JSONObject jsonObject, InputInfo inputInfo) {
        if (jsonObject == null) {
            return;
        }
        JSONObject aiOut = jsonObject.getJSONObject(entityRelationObject).getJSONObject(BeHospitalizedAI.outputs);
        if (aiOut == null) {
            return;
        }
        //诊断信息
        EntityProcessDiag entityProcessDiag = new EntityProcessDiag();
        List<Diag> diags = entityProcessDiag.extractEntity(aiOut);

        DiagLabel initialDiagLabel = new DiagLabel();
        initialDiagLabel.setText(inputInfo.getBeHospitalizedDoc().getInitialDiagLabel().getText());
        initialDiagLabel.setDiags(diags);
        inputInfo.getBeHospitalizedDoc().setInitialDiagLabel(initialDiagLabel);

        //        //因为关系抽取未标注完成，先用规则
        //        String diagString = inputInfo.getBeHospitalizedDoc().getInitialDiagLabel().getText();
        //        if (StringUtils.isNotEmpty(diagString)) {
        //            String[] diagArray = diagString.split(",");
        //            List<Diag> diags = new ArrayList<>();
        //            for (String d : diagArray) {
        //                Diag diag = DiagEnhancer.create(d);
        //                diags.add(diag);
        //            }
        //            InitialDiagLabel initialDiagLabel = new InitialDiagLabel();
        //            initialDiagLabel.setDiags(diags);
        //        }
    }

    /**
     * 修正诊断信息提取
     *
     * @param jsonObject
     * @param inputInfo
     */
    public void putRevisedDiagCrfData(JSONObject jsonObject, InputInfo inputInfo) {
        if (jsonObject == null) {
            return;
        }
        JSONObject aiOut = jsonObject.getJSONObject(entityRelationObject).getJSONObject(BeHospitalizedAI.outputs);
        if (aiOut == null) {
            return;
        }
        //诊断信息
        EntityProcessDiag entityProcessDiag = new EntityProcessDiag();
        List<Diag> diags = entityProcessDiag.extractEntity(aiOut);

        DiagLabel revisedDiagLabel = new DiagLabel();
        revisedDiagLabel.setText(inputInfo.getBeHospitalizedDoc().getRevisedDiagLabel().getText());
        revisedDiagLabel.setDiags(diags);
        inputInfo.getBeHospitalizedDoc().setRevisedDiagLabel(revisedDiagLabel);

        //替换初步诊断中的第一个诊断信息
       /* DiagLabel initialDiagLabel = inputInfo.getBeHospitalizedDoc().getInitialDiagLabel();
        if (initialDiagLabel.getDiags().size() > 0 && diags.size() > 0) {
            initialDiagLabel.getDiags().remove(0);
            initialDiagLabel.getDiags().add(0, diags.get(0));
        }*/
    }

    /**
     * 补充诊断信息提取
     *
     * @param jsonObject
     * @param inputInfo
     */
    public void putSuppleDiagCrfData(JSONObject jsonObject, InputInfo inputInfo) {
        if (jsonObject == null) {
            return;
        }
        JSONObject aiOut = jsonObject.getJSONObject(entityRelationObject).getJSONObject(BeHospitalizedAI.outputs);
        if (aiOut == null) {
            return;
        }
        //诊断信息
        EntityProcessDiag entityProcessDiag = new EntityProcessDiag();
        List<Diag> diags = entityProcessDiag.extractEntity(aiOut);

        DiagLabel suppleDiagLabel = new DiagLabel();
        suppleDiagLabel.setText(inputInfo.getBeHospitalizedDoc().getSuppleDiagLabel().getText());
        suppleDiagLabel.setDiags(diags);
        inputInfo.getBeHospitalizedDoc().setSuppleDiagLabel(suppleDiagLabel);
    }

    /**
     * 辅助检查信息抽取
     *
     * @param jsonObject
     * @param inputInfo
     */
    public void putPacsCrfData(JSONObject jsonObject, InputInfo inputInfo) {
        if (jsonObject == null) {
            return;
        }
        JSONObject aiOut = jsonObject.getJSONObject(entityRelationObject).getJSONObject(BeHospitalizedAI.outputs);
        if (aiOut == null) {
            return;
        }
        //放置入inputinfo
        PacsLabel pacsLabel = inputInfo.getBeHospitalizedDoc().getPacsLabel();
        pacsLabel.setPacses(loadPacses(aiOut));
    }

    /**
     * 关系抽取疾病信息
     *
     * @param aiOut
     * @return
     */
    public List<Diag> loadDiags(JSONObject aiOut) {
        //诊断信息
        EntityProcessDiag entityProcessDiag = new EntityProcessDiag();
        List<Diag> diags = entityProcessDiag.extractEntity(aiOut);
        return diags;
    }

    /**
     * 关系抽取化验信息
     *
     * @param aiOut
     * @return
     */
    public List<Lis> loadLises(JSONObject aiOut) {
        //化验信息
        EntityProcessLis entityProcessLis = new EntityProcessLis();
        List<Lis> lises = entityProcessLis.extractEntity(aiOut);
        return lises;
    }

    /**
     * 关系抽取辅检信息
     *
     * @param aiOut
     * @return
     */
    public List<Pacs> loadPacses(JSONObject aiOut) {
        //辅检信息
        EntityProcessPacs entityProcessLis = new EntityProcessPacs();
        List<Pacs> pacses = entityProcessLis.extractEntity(aiOut);
        return pacses;
    }

    /**
     * 关系抽取体格检查
     *
     * @param aiOut
     * @return
     */
    public List<Vital> loadvital(JSONObject aiOut) {
        //一般情况描述信息
        EntityProcessVital entityProcessVital = new EntityProcessVital();
        List<Vital> vitals = entityProcessVital.extractEntity(aiOut);
        return vitals;
    }
}