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.dbanaly.util.RedisUtil;
import com.lantone.qc.dbanaly.util.SpecialStorageUtil;
import com.lantone.qc.kernel.client.CRFServiceClient;
import com.lantone.qc.kernel.client.ChiefPresentSimilarityServiceClient;
import com.lantone.qc.kernel.client.SimilarityServiceClient;
import com.lantone.qc.kernel.util.CatalogueUtil;
import com.lantone.qc.pub.model.entity.Annotation;
import com.lantone.qc.pub.model.entity.ChiefPresentAnnotation;
import com.lantone.qc.pub.model.vo.CRFVo;
import com.lantone.qc.pub.model.vo.ChiefPresentSimilarityVo;
import com.lantone.qc.pub.model.vo.SimilarityVo;
import com.lantone.qc.pub.util.SpringContextUtil;
import com.lantone.qc.pub.util.StringUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * @ClassName : ModelAI
 * @Description : 算法基类
 * @Author : 楼辉荣
 * @Date: 2020-03-19 15:08
 */
@Slf4j
public class ModelAI {
    /**
     * 获取CRF返回数据
     *
     * @param crfContent
     * @param crfServiceClient
     * @return
     */
    protected JSONObject loadAI(boolean useCrfCache, String behospitalCode, JSONArray crfContent, CRFServiceClient crfServiceClient) {
        JSONArray data = null;
        RedisUtil redisUtil = SpringContextUtil.getBean("redisUtil");
        SpecialStorageUtil specialStorageUtil = SpringContextUtil.getBean("specialStorageUtil");
        String prex = "crf_cache:" + specialStorageUtil.getHospitalIdThreadLocal().get() + ":";
        String classname = this.getClass().getName();
        if (useCrfCache) {
            data = (JSONArray) redisUtil.hget(prex + behospitalCode, classname);
        }
        if (data == null) {
            //存储CRF完整所需结构数据
            CRFVo crfVo = new CRFVo();
            crfVo.setData(crfContent);
            long t1 = System.currentTimeMillis();
            //获取CRF模型返回数据
            data = getAnnotation(crfServiceClient, crfVo).getData();
            long t2 = System.currentTimeMillis();
            log.error(behospitalCode + "-----" + classname + "（CRF）  耗时：" + (t2 - t1));
            if (data != null) {
                redisUtil.hset(prex + behospitalCode, classname, data, 86400);
            }
        }
        JSONObject midData = getOutputs(data);
        return midData;
    }

    protected JSONObject loadEntity(JSONObject jsonObject, String entityRelationObject, String outputs, String content) {
        if (jsonObject == null) {
            return new JSONObject();
        }
        JSONObject aiOut = jsonObject.getJSONObject(entityRelationObject).getJSONObject(outputs);
        aiOut.put(content, jsonObject.getJSONObject(entityRelationObject).getString(content));
        return aiOut;
    }

    private Annotation getAnnotation(CRFServiceClient crfServiceClient, CRFVo crfVo) {
        Annotation annotation = new Annotation();
        try {
            String annotation_str = crfServiceClient.getAnnotation(crfVo);
            annotation = JSON.parseObject(annotation_str, Annotation.class);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            return annotation;
        }
    }

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

    protected void putContent(JSONArray crfContent, String medicalTextType, String firstText, String secondText, String sign) {
        String firstMoveText = CatalogueUtil.removeSpecialChar(firstText);
        String secondMoveText = CatalogueUtil.removeSpecialChar(secondText);
        if (StringUtil.isEmpty(firstMoveText) && StringUtil.isEmpty(secondMoveText)) {
            return;
        }
        JSONObject detailContent = new JSONObject();
        detailContent.put("medical_text_type", medicalTextType);
        detailContent.put("content", firstMoveText + "\n" + secondMoveText);
        detailContent.put("detail_title", sign);
        crfContent.add(detailContent);
    }

    /**
     * 获取CRF模型输出并处理
     *
     * @param data
     * @return
     */
    public JSONObject getOutputs(JSONArray data) {
        JSONObject midData = new JSONObject();
        for (int i = 0; i < data.size(); i++) {
            JSONObject detailContent = data.getJSONObject(i);
            String detail_title = detailContent.getString("detail_title");
            if (StringUtil.isNotEmpty(detail_title) && midData.get(detail_title) == null) {
                midData.put(detail_title, detailContent);
            }
        }
        return midData;
    }

    /*****************************文本相似度算法************************************/

    /**
     * 存放文本相似度入参内容
     *
     * @param similarContent
     * @param firstText
     * @param secondText
     */
    public void putContent(JSONArray similarContent, String firstText, String secondText) {
        String moveFirstText = CatalogueUtil.removeSpecialChar(firstText);
        String moveSecondText = CatalogueUtil.removeSpecialChar(secondText);
        if (StringUtil.isEmpty(moveFirstText) || StringUtil.isEmpty(moveSecondText)) {
            return;
        }
        JSONObject detailContent = new JSONObject();
        detailContent.put("text_1", moveFirstText);
        detailContent.put("text_2", moveSecondText);
        similarContent.add(detailContent);
    }

    private Annotation getAnnotation(SimilarityServiceClient similarityServiceClient, SimilarityVo similarityVo) {
        Annotation annotation = new Annotation();
        try {
            String annotation_str = similarityServiceClient.getAnnotation(similarityVo);
            annotation = JSON.parseObject(annotation_str, Annotation.class);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            return annotation;
        }
    }

    /**
     * 获取文本相似度返回数据
     *
     * @param similarContent
     * @param similarityServiceClient
     * @return
     */
    public double loadSimilarAI(JSONArray similarContent, SimilarityServiceClient similarityServiceClient) {
        //存储CRF完整所需结构数据
        SimilarityVo similarityVo = new SimilarityVo();
        similarityVo.setData(similarContent);
        //获取CRF模型返回数据
        JSONArray data = getAnnotation(similarityServiceClient, similarityVo).getData();
        return getSimilarOutputs(data);
    }

    /**
     * 获取文本相似度模型输出并处理
     *
     * @param data 数组里只有一个对象
     * @return
     */
    public double getSimilarOutputs(JSONArray data) {
        double likeRate = 0d;
        if (data.size() > 0) {
            JSONObject dataContent = data.getJSONObject(0);
            likeRate = dataContent.getDoubleValue("like_rate");
        }
        return likeRate;
    }
    /*****************************主诉现病史症状文本相似度算法************************************/

    /**
     * 存放主诉现病史症状文本相似度入参内容
     */
    public void putContent(JSONObject similarContent, String firstText, List<String> clinicArr) {
        if (StringUtil.isEmpty(firstText) || clinicArr.size() == 0) {
            return;
        }
        similarContent.put("string1", firstText);
        similarContent.put("string2", clinicArr);
    }

    /**
     * 获取主诉现病史症状相似度返回数据
     *
     * @param string1
     * @param string2
     * @param chiefPresentSimilarityServiceClient
     * @return
     */
    public JSONArray loadChiefPresentSimilarAI(String string1, List<String> string2, boolean directionCheck
            , String modelName, ChiefPresentSimilarityServiceClient chiefPresentSimilarityServiceClient) {
        //存储CRF完整所需结构数据
        ChiefPresentSimilarityVo similarityVo = new ChiefPresentSimilarityVo();
        JSONObject data = new JSONObject();
        putContent(data, string1, string2);
        similarityVo.setData(data);
        similarityVo.setDirection_check(directionCheck);
        similarityVo.setModel_name(modelName);
        //获取CRF模型返回数据
        JSONArray predY = getAnnotation(chiefPresentSimilarityServiceClient, similarityVo).getPred_y();
        return getChiefPresentSimilarOutputs(predY);
    }

    /**
     * 主诉现病史相似度接口返回
     *
     * @param chiefPresentSimilarityServiceClient
     * @param chiefPresentSimilarityVo
     * @return
     */
    private ChiefPresentAnnotation getAnnotation(ChiefPresentSimilarityServiceClient chiefPresentSimilarityServiceClient,
                                                 ChiefPresentSimilarityVo chiefPresentSimilarityVo) {
        ChiefPresentAnnotation annotation = new ChiefPresentAnnotation();
        try {
            String annotation_str = chiefPresentSimilarityServiceClient.getAnnotation(chiefPresentSimilarityVo);
            annotation = JSON.parseObject(annotation_str, ChiefPresentAnnotation.class);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            return annotation;
        }
    }

    /**
     * 获取主诉现病史文本相似度模型输出并处理
     *
     * @param predY
     * @return
     */
    public JSONArray getChiefPresentSimilarOutputs(JSONArray predY) {
        JSONArray dataArr = new JSONArray();
        if (predY != null && predY.size() > 0) {
            dataArr = predY.getJSONArray(0);
        }
        return dataArr;
    }
}