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

import com.alibaba.fastjson.JSONObject;
import com.lantone.qc.kernel.structure.ai.model.EntityEnum;
import com.lantone.qc.kernel.structure.ai.model.Lemma;
import com.lantone.qc.pub.model.entity.*;
import com.lantone.qc.pub.model.label.ThreeLevelWardLabel;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

/**
 * @ClassName : EntityProcessThreeLevelWard
 * @Description : 查房记录
 * @Author : 胡敬
 * @Date: 2020-03-20 11:20
 */
@Slf4j
public class EntityProcessThreeLevelWard extends EntityProcess {
    private List<String> titleList = Arrays.asList(
            EntityEnum.TITLE_FOR_SIGN.toString(),
            EntityEnum.TITLE_FOR_DIAG.toString(),
            EntityEnum.TITLE_FOR_DIAG_BASIS.toString(),
            EntityEnum.TITLE_FOR_DIFF.toString(),
            EntityEnum.TITLE_FOR_TREAT.toString());

    public ThreeLevelWardLabel extractEntity(JSONObject aiOut) {
        ThreeLevelWardLabel threeLevelWardLabel = new ThreeLevelWardLabel();
        String content = aiOut.getString("content");

        Map<String, List<String>> titleText = subWithTitle(aiOut);
        //全部临床表现实体
        List<Lemma> clinicalLemmas = createEntityTree(aiOut, EntityEnum.CLINICAL_FEATURE.toString());
        //全部诊断
        List<Lemma> diagLemmas = createEntityTree(aiOut, EntityEnum.DIEASE.toString());
        //诊断依据
        if (titleText.get(EntityEnum.TITLE_FOR_DIAG_BASIS.toString()) != null) {
            List<String> diagBasisList = titleText.get(EntityEnum.TITLE_FOR_DIAG_BASIS.toString());
            String text = textJoin(content, diagBasisList);
            String[] diagBasisSplit = String.join(",", diagBasisList).split(",");
            //诊断依据文本
            threeLevelWardLabel.setDiagBasisText(text);
            //病史(在 诊断依据 以外的片段中出现 任一 临床表现)
            addClinical(threeLevelWardLabel, diagBasisSplit, clinicalLemmas);
            //补充诊断/初步诊断/修正诊断
            addDiag(threeLevelWardLabel, diagBasisSplit, diagLemmas);
        }

        //诊断文本
        if (titleText.get(EntityEnum.TITLE_FOR_DIAG.toString()) != null) {
            List<String> diagList = titleText.get(EntityEnum.TITLE_FOR_DIAG.toString());
            String text = textJoin(content, diagList);
            //诊断文本
            threeLevelWardLabel.setDiagText(text);
        }

        //鉴别诊断
        if (titleText.get(EntityEnum.TITLE_FOR_DIFF.toString()) != null) {
            List<String> diffDiagList = titleText.get(EntityEnum.TITLE_FOR_DIFF.toString());
            String diagBasis = String.join(",", diffDiagList);
            String[] diffDiagSplit = diagBasis.split(",");
            //病史(在 鉴别诊断 以外的片段中出现 任一 临床表现)
            addClinical(threeLevelWardLabel, diffDiagSplit, clinicalLemmas);
            //补充诊断/初步诊断/修正诊断
            addDiag(threeLevelWardLabel, diffDiagSplit, diagLemmas);
            //添加鉴别诊断
            List<Diag> diags = new ArrayList<>();
            for (Lemma dieaseLemma : diagLemmas) {
                if (Integer.parseInt(dieaseLemma.getPosition()) < Integer.parseInt(diffDiagSplit[0])
                        || Integer.parseInt(dieaseLemma.getPosition()) > Integer.parseInt(diffDiagSplit[diffDiagSplit.length - 1])) {
                    continue;
                }
                Diag diag = new Diag();
                diag.setHospitalDiagName(dieaseLemma.getText());
                diags.add(diag);
            }
            threeLevelWardLabel.setDiffDiag(diags);
            List<Lemma> diagDiffLemmas = createEntityTree(aiOut, EntityEnum.TITLE_FOR_DIFF.toString());
            for (Lemma lemma : diagDiffLemmas) {
                if (lemma.getText().contains("诊断明确") || lemma.getText().contains("无需鉴别")) {
                    threeLevelWardLabel.setDiffDiagText(lemma.getText());
                    break;
                }
            }
        }

        //没有诊断依据和鉴别诊断情况下，添加诊断
        if (titleText.get(EntityEnum.TITLE_FOR_DIAG_BASIS.toString()) == null
                && titleText.get(EntityEnum.TITLE_FOR_DIFF.toString()) == null) {
            //补充诊断/初步诊断/修正诊断
            addDiag(threeLevelWardLabel, diagLemmas);
        }

        //查体
        List<Lemma> signLemmas = createEntityTree(aiOut, EntityEnum.PHYSICAL_EXAMINATION.toString());
        List<Sign> signs = new ArrayList<>();
        for (Lemma lemma : signLemmas) {
            Sign sign = new Sign();
            sign.setName(lemma.getText());
            signs.add(sign);
        }
        threeLevelWardLabel.setSigns(signs);

        //诊疗计划
        List<Lemma> treatmentPlanLemmas = createEntityTree(aiOut, EntityEnum.TREATMENT_PLAN.toString());
        List<TreatmentPlan> treatmentPlans = new ArrayList<>();
        for (Lemma lemma : treatmentPlanLemmas) {
            TreatmentPlan treatmentPlan = new TreatmentPlan();
            treatmentPlan.setName(lemma.getText());
            treatmentPlans.add(treatmentPlan);
        }
        threeLevelWardLabel.setTreatmentPlans(treatmentPlans);

        //离院方式
        List<Lemma> dischargeMode = createEntityTree(aiOut, EntityEnum.DISCHARGE_MODE.toString());
        for (Lemma lemma : dischargeMode) {
            String text = lemma.getText();
            threeLevelWardLabel.setDischargeMode(text);
        }


        //好转表现
        List<Lemma> betterFindingLemmas = createEntityTree(aiOut, EntityEnum.BETTER_FINDING.toString());
        List<BetterFinding> betterFindings = new ArrayList<>();
        for (Lemma lemma : betterFindingLemmas) {
            BetterFinding betterFinding = new BetterFinding();
            betterFinding.setName(lemma.getText());
            betterFindings.add(betterFinding);
        }
        threeLevelWardLabel.setBetterFindings(betterFindings);

        //转归情况-好转
        List<Lemma> outcomeToBetterLemmas = createEntityTree(aiOut, EntityEnum.OUTCOME_TO_BETTER.toString());
        List<OutcomeToBetter> outcomeToBetters = new ArrayList<>();
        for (Lemma lemma : outcomeToBetterLemmas) {
            OutcomeToBetter outcomeToBetter = new OutcomeToBetter();
            outcomeToBetter.setName(lemma.getText());
            outcomeToBetters.add(outcomeToBetter);
        }
        threeLevelWardLabel.setOutcomeToBetters(outcomeToBetters);

        //转归情况-治愈
        List<Lemma> outcomeCureLemmas = createEntityTree(aiOut, EntityEnum.OUTCOME_CURE.toString());
        List<OutcomeCure> outcomeCures = new ArrayList<>();
        for (Lemma lemma : outcomeCureLemmas) {
            OutcomeCure outcomeCure = new OutcomeCure();
            outcomeCure.setName(lemma.getText());
            outcomeCures.add(outcomeCure);
        }
        threeLevelWardLabel.setOutcomeCures(outcomeCures);

        //阳性表现
        List<Lemma> positiveFindingLemmas = createEntityTree(aiOut, EntityEnum.POSITIVE_FINDING.toString());
        List<PositiveFinding> positiveFindings = new ArrayList<>();
        for (Lemma lemma : positiveFindingLemmas) {
            PositiveFinding positiveFinding = new PositiveFinding();
            positiveFinding.setName(lemma.getText());
            positiveFindings.add(positiveFinding);
        }
        threeLevelWardLabel.setPositiveFindings(positiveFindings);

        try {
            //实验室检查套餐
            List<LaboratoryPackage> laboratoryPackages = new ArrayList<>();
            List<Lemma> laboratoryPackageLemmas = createEntityTree(aiOut, EntityEnum.LABORATORY_PACKAGE.toString());
            for (Lemma lemma : laboratoryPackageLemmas) {
                LaboratoryPackage laboratoryPackage = new LaboratoryPackage();
                laboratoryPackage.setName(lemma.getText());
                laboratoryPackage.setCheckTime(findTAfter(lemma, new CheckTime(), EntityEnum.CHECK_TIME.toString()));
                laboratoryPackages.add(laboratoryPackage);
            }
            threeLevelWardLabel.setLaboratoryPackages(laboratoryPackages);

            //实验室检查
            List<Laboratory> laboratories = new ArrayList<>();
            List<Lemma> laboratoryLemmas = createEntityTree(aiOut, EntityEnum.LABORATORY.toString());
            for (Lemma lemma : laboratoryLemmas) {
                Laboratory laboratory = new Laboratory();
                laboratory.setName(lemma.getText());
                for (Lemma relationLemma : lemma.getRelationLemmas()) {
                    if (relationLemma.getProperty().equals(EntityEnum.LABORATORY_PACKAGE.toString())) {
                        LaboratoryPackage laboratoryPackage = new LaboratoryPackage();
                        laboratoryPackage.setCheckTime(findTAfter(lemma, new CheckTime(), EntityEnum.CHECK_TIME.toString()));
                        laboratory.setLaboratoryPackage(findTAfter(lemma, laboratoryPackage, EntityEnum.LABORATORY_PACKAGE.toString()));//实验室检查套餐
                    }
                }
                laboratory.setCheckTime(findTAfter(lemma, new CheckTime(), EntityEnum.CHECK_TIME.toString()));//检查时间
                laboratory.setLaboratoryResults(findTAfter(lemma, new LaboratoryResults(), EntityEnum.LABORATORY_RESULTS.toString()));//实验室检查结果
                laboratories.add(laboratory);
            }
            threeLevelWardLabel.setLaboratories(laboratories);

            //辅助检查
            List<AuxiliaryExamination> auxiliaryExaminations = new ArrayList<>();
            List<Lemma> auxiliaryExaminationLemmas = createEntityTree(aiOut, EntityEnum.AUXILIARY_EXAMINATION.toString());
            for (Lemma lemma : auxiliaryExaminationLemmas) {
                AuxiliaryExamination auxiliaryExamination = new AuxiliaryExamination();
                auxiliaryExamination.setName(lemma.getText());
                auxiliaryExamination.setCheckTime(findTAfter(lemma, new CheckTime(), EntityEnum.CHECK_TIME.toString()));
                auxiliaryExamination.setAuxiliaryExaminationResults(findTAfter(lemma, new AuxiliaryExaminationResults(), EntityEnum.AUXILIARY_EXAMINATION_RESULTS.toString()));
                auxiliaryExaminations.add(auxiliaryExamination);
            }
            threeLevelWardLabel.setAuxiliaryExaminations(auxiliaryExaminations);

            //药物
            List<Drug> drugs = new ArrayList<>();
            List<Lemma> DrugLemmas = createEntityTree(aiOut, EntityEnum.DRUG.toString());
            for (Lemma lemma : DrugLemmas) {
                int lemmaPosition = Integer.parseInt(lemma.getPosition());
                if (content.substring(Math.max(0, lemmaPosition - 10), lemmaPosition).contains("暂停")){
                    continue;
                }
                Drug drug = new Drug();
                drug.setName(lemma.getText());
                drug.setConsumption(findTAfter(lemma, new Consumption(), EntityEnum.CONSUMPTION.toString().split("-")[0]));
                drug.setUsageWardRound(findTAfter(lemma, new UsageWardRound(), EntityEnum.USAGE_WARD_ROUND.toString()));
                drug.setFrequency(findTAfter(lemma, new Frequency(), EntityEnum.FREQUENCY.toString()));
                drug.setStop(findTAfter(lemma, new Stop(), EntityEnum.STOP.toString()));
                drug.setReasonsForAntibiotic(findTAfter(lemma, new ReasonsForAntibiotic(), EntityEnum.REASONS_FOR_ANTIBIOTIC.toString()));
                drugs.add(drug);
            }
            threeLevelWardLabel.setDrugs(drugs);

        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
        }
        return threeLevelWardLabel;
    }

    private String textJoin(String content, List<String> operativeFindingsList) {
        StringBuffer text = new StringBuffer();
        for (String titleTextIndex : operativeFindingsList) {
            String[] titleTextIndexSplit = titleTextIndex.split(",");
            text.append(content.substring(Integer.parseInt(titleTextIndexSplit[0]),
                    Integer.parseInt(titleTextIndexSplit[1])));
        }
        return text.toString();
    }

    /**
     * 根据各标题截取文本index
     *
     * @param aiOut
     * @return
     */
    private Map<String, List<String>> subWithTitle(JSONObject aiOut) {
        Map<String, List<String>> titleText = new LinkedHashMap<>();
        String content = aiOut.getString("content");
        List<Lemma> lemmaList = loadAllLemmaList(aiOut.getJSONObject("annotation").getJSONArray("T"));
        Lemma lemma;
        int start = 0;
        String subContentIndex = "", title = "";
        for (int i = 0; i < lemmaList.size(); i++) {
            lemma = lemmaList.get(i);
            if (!titleList.contains(lemma.getProperty()) && i != lemmaList.size() - 1) {
                continue;
            }
            if (i != lemmaList.size() - 1) {
                if (start == 0) {
                    start = Integer.parseInt(lemma.getPosition());
                    title = lemma.getProperty();//截取的这一段文本的标题
                } else {
                    /*subContentIndex = start + lemma.getText().length() + 1 + "," + Integer.parseInt(lemma.getPosition());*/
                    subContentIndex = start + "," + Integer.parseInt(lemma.getPosition());
                    putSubContent(titleText, title, subContentIndex);
                    start = Integer.parseInt(lemma.getPosition());
                    title = lemma.getProperty();//截取的这一段文本的标题
                }
            } else {
                //将倒数第二个标题存入结构
                subContentIndex = start + "," + Integer.parseInt(lemma.getPosition());
                putSubContent(titleText, title, subContentIndex);
                //如果是最后一个Lemma，文本就从当前lemma的position开始取，取到结束
                title = lemma.getProperty();//截取的这一段文本的标题
                if (titleList.contains(title)) {
                    start = Integer.parseInt(lemma.getPosition());
                    int lastIndex = content.length() - 1;
                    subContentIndex = start + "," + lastIndex;
                    putSubContent(titleText, title, subContentIndex);
                }
            }
        }
        return titleText;
    }

    private void putSubContent(Map<String, List<String>> titleText, String text, String subContent) {
        List<String> textList;
        if (titleText.containsKey(text)) {
            titleText.get(text).add(subContent);
        } else {
            textList = new ArrayList<>();
            textList.add(subContent);
            titleText.put(text, textList);
        }
    }

    /**
     * 添加病史(临床表现)
     *
     * @param threeLevelWardLabel
     * @param indexArray          标题对应文本全部起始位置、结束位置信息
     * @param clinicalLemmas
     */
    private void addClinical(ThreeLevelWardLabel threeLevelWardLabel, String[] indexArray, List<Lemma> clinicalLemmas) {
        List<Clinical> clinicals = new ArrayList<>();
        for (Lemma lemma : clinicalLemmas) {
            if (Integer.parseInt(lemma.getPosition()) > Integer.parseInt(indexArray[0])
                    && Integer.parseInt(lemma.getPosition()) < Integer.parseInt(indexArray[indexArray.length - 1])) {
                continue;
            }
            Clinical clinical = new Clinical();
            clinical.setName(lemma.getText());
            clinicals.add(clinical);
        }
        if (threeLevelWardLabel.getClinicals().size() == 0) {
            threeLevelWardLabel.setClinicals(clinicals);
        } else {
            threeLevelWardLabel.getClinicals().addAll(clinicals);
        }
    }

    /**
     * 添加补充诊断/初步诊断/修正诊断
     *
     * @param threeLevelWardLabel
     * @param indexArray          标题对应文本全部起始位置、结束位置信息
     * @param diagLemmas
     */
    private void addDiag(ThreeLevelWardLabel threeLevelWardLabel, String[] indexArray, List<Lemma> diagLemmas) {
        List<Diag> diags = new ArrayList<>();
        for (Lemma lemma : diagLemmas) {
            if (Integer.parseInt(lemma.getPosition()) > Integer.parseInt(indexArray[0])
                    && Integer.parseInt(lemma.getPosition()) < Integer.parseInt(indexArray[indexArray.length - 1])) {
                continue;
            }
            Diag diag = new Diag();
            diag.setHospitalDiagName(lemma.getText());
            diags.add(diag);
        }
        if (threeLevelWardLabel.getDiags().size() == 0) {
            threeLevelWardLabel.setDiags(diags);
        } else {
            threeLevelWardLabel.getDiags().addAll(diags);
        }
    }

    /**
     * 没有诊断依据和鉴别诊断情况下，添加诊断
     *
     * @param threeLevelWardLabel
     * @param diagLemmas
     */
    private void addDiag(ThreeLevelWardLabel threeLevelWardLabel, List<Lemma> diagLemmas) {
        List<Diag> diags = new ArrayList<>();
        for (Lemma lemma : diagLemmas) {
            Diag diag = new Diag();
            diag.setHospitalDiagName(lemma.getText());
            diags.add(diag);
        }
        if (threeLevelWardLabel.getDiags().size() == 0) {
            threeLevelWardLabel.setDiags(diags);
        } else {
            threeLevelWardLabel.getDiags().addAll(diags);
        }
    }

}