package org.diagbot.graphWeb.work;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.diagbot.common.javabean.MangementEvaluation;
import org.diagbot.common.work.FeatureRate;
import org.diagbot.common.javabean.Filnlly;
import org.diagbot.common.work.LisDetail;
import org.diagbot.common.work.ResponseData;
import org.diagbot.common.work.SearchData;
import org.diagbot.graph.jdbc.DriverManager;
import org.diagbot.graph.jdbc.Neo4jAPI;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

import org.diagbot.common.javabean.MedicalIndication;
import org.diagbot.common.javabean.MedicalIndicationDetail;
import org.diagbot.graph.util.CacheUtil;
import org.diagbot.graphWeb.util.MapValueComparator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GraphCalculate {
    Logger logger = LoggerFactory.getLogger(GraphCalculate.class);
    private static Neo4jAPI neo4jAPI ;

    /**
     * 返回诊断和治疗
     *
     * @param request
     * @param searchData
     * @return
     * @throws Exception
     */
    public ResponseData calculate(HttpServletRequest request, SearchData searchData) throws Exception {

        long starttime = System.currentTimeMillis();
        System.out.println("Start at: " + starttime);

        ResponseData responseData = new ResponseData();
//        ParamsDataProxy paramsDataProxy = new ParamsDataProxy();
//        paramsDataProxy.createSearchData(request, searchData);
        List<String> inputList = new ArrayList<>();
        int age = searchData.getAge();
        String sex = searchData.getSex();
        logger.info("前端传来的年龄为 :"+age+" 前端传来的性别为 :"+sex);
        //获取缓存
//        Map<String, String> lexionCache = CacheUtil.getLexionCache();
        Map<String, Map<String, String>> sexAgeCache = CacheUtil.getSexAgeCache();
        Map<String, Map<String, String>> inputs = searchData.getGraphInputs();
        Set<String> ss = new HashSet<>();
        if(inputs.size()>0){
            for (Map.Entry<String, Map<String, String>> input:inputs.entrySet()) {
                Map<String, String> value = input.getValue();
                String concept = value.get("concept");
                String[] splits = StringUtils.split(concept, ",");
                for (String s:splits) {
                    ss.add(s);
                }
            }
        }
        logger.info("从分词系统接收到的词 :" + ss);
        System.out.println("Participle takes: " + (System.currentTimeMillis()-starttime)/1000d + 's');

        List<String> featureTypeList = Arrays.asList(searchData.getFeatureTypes());
        logger.info("featureTypeList : " + featureTypeList);
        inputList.addAll(ss);
        if(neo4jAPI == null){
            neo4jAPI = new Neo4jAPI(DriverManager.newDrive());
        }
        logger.info("图谱开始推送诊断!!!!!!!!!!!");
        String webDiag = searchData.getDiag();
        logger.info("页面诊断为 :"+webDiag);
        //计算诊断
        Map<String, Map<String,String>> condition =null;
        Map<String, Map<String, String>> excludelist = null;
        if(featureTypeList.contains("2")){
            condition = neo4jAPI.getNewCondition((String[]) inputList.toArray(new String[inputList.size()]),webDiag );

            // 查找需要排除的诊断
            excludelist = neo4jAPI.getExcludeDiag(inputList);
            responseData.setExcludeDiag(Arrays.asList(excludelist.keySet().stream().toArray(String[]::new)));
        }

        List<FeatureRate> featureRates = new ArrayList<>();
        if(condition != null){
            for (Map.Entry<String, Map<String,String>> d : condition.entrySet()) {
                String dis = d.getKey();
                Map<String, String> sexAgeMap = sexAgeCache.get(dis);
                if(sexAgeMap != null){
                    String sexType = sexAgeMap.get("sexType");
                    Integer min_age = Integer.parseInt(sexAgeMap.get("min_age"));
                    Integer max_age = Integer.parseInt(sexAgeMap.get("max_age"));

                    if(("1".equals(sexType) &&sex.equals(sexType)) || ("2".equals(sexType) &&sex.equals(sexType)) || "3".equals(sexType)){
                        if(min_age <age && age<=max_age){
                            FeatureRate featureRate = new FeatureRate();
                            featureRate.setFeatureName(dis);
                            Map<String, String> value = d.getValue();
                            String s = JSON.toJSONString(value);
                            featureRate.setDesc(s);
//                            featureRate.setRate("neo4j");
                            featureRate.setSource("neo4j");
                            featureRates.add(featureRate);
                        }

                    }
                }
            }
        }
        Set<String> diseaseSet =null;
        if(condition != null){
            diseaseSet = condition.keySet();
            logger.info("diseaseSet :" + diseaseSet);
        }
        Integer diseaseType = searchData.getDisType();
        List<LisDetail> lisArr = searchData.getLisArr();
        Set<String> lisSet = new HashSet<>();
        Map<String,Double> lis_Result = new HashMap<>();
        if(lisArr != null && lisArr.size() > 0){
            for (LisDetail lis:lisArr) {
                String detailName = lis.getUniqueName();
                logger.info("公表名为  :"+detailName);
                Double value = lis.getValue();
                lis_Result.put(detailName,value);
                lisSet.add(detailName);
            }
        }
        logger.info("页面导入的所有化验项为 :" +lisSet);

        //走治疗
        if (webDiag !=null && webDiag.trim() != null && webDiag.trim() != "" && featureTypeList.contains("6")) {
            // 查找页面诊断里是否有不良反应
            String[] webDiagList = webDiag.split(",|，|、|;|:|；");
            Map<String, List<String>> disUE = neo4jAPI.getDisUE(webDiagList, diseaseType);
            //根据页面输入内容推出的不良反应集合
            Set<String> ue = neo4jAPI.getUe((String[]) inputList.toArray(new String[inputList.size()]));
            //走平常诊断治疗
            Map<String, Filnlly> mulDiseaseTreat = neo4jAPI.getMulDiseaseTreat_2(webDiag, diseaseType, diseaseSet,disUE,ue,String.join(",", inputList));
            responseData.setTreat(mulDiseaseTreat);
        }
        //管理评估(慢病才有)
        if (featureTypeList.contains("11") && diseaseType == 1 && diseaseType != null) {
            logger.info("featureTypeList 包含11,走管理评估!!!");
            if(webDiag != null){
                String[] webDiagsplits = webDiag.split(",|，|、|;|:|；");
                MangementEvaluation mangementEvaluation = neo4jAPI.pushMe(webDiagsplits,lis_Result);
                Map<String, JSONObject> mangementEvaluation1 = mangementEvaluation.getMangementEvaluation();
                responseData.setManagementEvaluation(mangementEvaluation1);
            }
        }

        //指标推送
        if (featureTypeList.contains("22") ) {
            //查找指标
            Set<String> indSet = neo4jAPI.getInd((String[]) inputList.toArray(new String[inputList.size()]));
            logger.info("featureTypeList 包含22,走指标推送!!!,图谱推出的指标为:" + indSet);
            if(indSet.contains("肾功能不全")){
                List<MedicalIndication> idn = neo4jAPI.getIdn(indSet, age, sex);
                responseData.setMedicalIndications(idn);
            }
        }

        //诊断推送
        responseData.setDis(featureRates);
        responseData.setInputs(searchData.getInputs());

        System.out.println("Total takes: " + (System.currentTimeMillis()-starttime)/1000d + 's');
        return responseData;
    }
//    诊断过滤
    public void filterDis(List<FeatureRate> graphFeatureRates,String sex,Integer age) throws Exception {
        if(neo4jAPI == null){
            neo4jAPI = new Neo4jAPI(DriverManager.newDrive());
        }
        List<String> disList = new ArrayList<>();
        if(graphFeatureRates != null && graphFeatureRates.size()>0){
            for (FeatureRate f:graphFeatureRates) {
                disList.add("\""+f.getFeatureName()+"\"");
            }
        }
//        第一步先过滤性别和年龄
        Set<String> filterSexAgeList = neo4jAPI.filterDisFromSexAge(disList,sex,age);


    }
    /**
     * 返回LIS,PACS
     *
     * @param searchData
     */
    public ResponseData getLisPacs(HttpServletRequest request, SearchData searchData) throws Exception {
        ResponseData responseData = new ResponseData();
        Neo4jAPI neo4jAPI = new Neo4jAPI(DriverManager.newDrive());
        String webDiag = searchData.getDiag();
        List<String> webDiagList = Arrays.asList(webDiag.split(",|，|、"));
        List<FeatureRate> bigdataDiagFeature = searchData.getPushDiags();
        List<String> bigdataDiagList = new LinkedList<>();
        if (bigdataDiagFeature.size() > 0) {
            for (FeatureRate fe : bigdataDiagFeature) {
                if ("neo4j".equals(fe.getRate())) {
                    bigdataDiagList.add(fe.getFeatureName());
                    logger.info("图谱推出的诊断为: " + fe.getFeatureName());
                } else {
                    bigdataDiagList.add(fe.getFeatureName());
                    logger.info("大数据推出的诊断为: " + fe.getFeatureName());
                }
            }
        }
        for (String web : webDiagList) {
            for (int i = 0; i < bigdataDiagList.size(); i++) {
                if (bigdataDiagList.get(i).equals(web)) {
                    bigdataDiagList.remove(bigdataDiagList.get(i));
                }
            }
        }
        logger.info("界面诊断为: " + webDiagList);
        logger.info("推出的诊断合并为: " + bigdataDiagList);
        Map<String, Set<String>> weblisPacs1 = null;
        Map<String, Set<String>> biglisPacs1 = null;
        if (webDiagList != null && webDiagList.size() > 0) {
            weblisPacs1 = neo4jAPI.getLisPacs(webDiagList);//界面诊断推出的LIS,PACS
        }
        if (bigdataDiagList != null && bigdataDiagList.size() > 0) {
            biglisPacs1 = neo4jAPI.getLisPacs(bigdataDiagList);//大数据推得诊断
        }
        Set<String> lis = null;
        Set<String> pacs = null;
        //如果界面有诊断
        if (weblisPacs1 != null && weblisPacs1.values().size() > 0) {
            lis = weblisPacs1.get("LIS");
            pacs = weblisPacs1.get("PACS");
            logger.info("界面有诊断的情况下,界面诊断推出的lis为: " + lis);
            logger.info("界面有诊断的情况下,界面诊断推出的pacs为: " + pacs);
            if (biglisPacs1 != null && biglisPacs1.values().size() > 0) {
                Set<String> bl = biglisPacs1.get("LIS");
                Set<String> bp = biglisPacs1.get("PACS");
                logger.info("界面有诊断的情况下,推出诊断的lis为: " + bl);
                logger.info("界面有诊断的情况下,推出诊断的pacs为: " + bp);
                lis.addAll(bl);
                pacs.addAll(bp);
            }
        } else {
            lis = biglisPacs1.get("LIS");
            pacs = biglisPacs1.get("PACS");
            logger.info("界面无诊断的情况下,推出诊断的lis为: " + lis);
            logger.info("界面无诊断的情况下,推出诊断的lis为: " + pacs);
        }
        logger.info("推出的合并lis为: " + lis);
        logger.info("推出的合并pacs为: " + pacs);
        ArrayList<FeatureRate> lisFeature = new ArrayList<>();
        ArrayList<FeatureRate> pacsFeature = new ArrayList<>();
        for (String l : lis) {
            FeatureRate featureRate = new FeatureRate();
            featureRate.setFeatureName(l);
            lisFeature.add(featureRate);
        }
        for (String p : pacs) {
            FeatureRate featureRate = new FeatureRate();
            featureRate.setFeatureName(p);
            pacsFeature.add(featureRate);
        }
        responseData.setLabs(lisFeature);
        responseData.setPacs(pacsFeature);
        return responseData;
    }


    /**
     * 对化验和检查的结果进行排序
     *
     * @param set
     * @return List<FeatureRate>
     */
    public Set<String> processResult(Set<String> set) {
        Set<String> frlist = new LinkedHashSet<>();
        Map<String, String> sortval = new HashMap<>();
        Map<String, String> items = new HashMap<>();
        String name;
        try {
            if (set != null && set.size() > 0) {
                for (String item : set) {
                    if (sortval.get(item) == null) {
                        sortval.put(item, "1");
                    } else {
                        sortval.put(item, String.valueOf(Integer.parseInt(sortval.get(item)) + 1));
                    }
                }
                sortval = sortMapByValue(sortval);
                for (String key : sortval.keySet()) {
                    frlist.add(items.get(key));
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            return frlist;
        }
    }


    /**
     * 使用 Map按value进行排序
     *
     * @param oriMap
     * @return
     */
    public static Map<String, String> sortMapByValue(Map<String, String> oriMap) {
        if (oriMap == null || oriMap.isEmpty()) {
            return null;
        }
        Map<String, String> sortedMap = new LinkedHashMap<String, String>();
        List<Map.Entry<String, String>> entryList = new ArrayList<Map.Entry<String, String>>(
                oriMap.entrySet());
        Collections.sort(entryList, new MapValueComparator());
        Iterator<Map.Entry<String, String>> iter = entryList.iterator();
        Map.Entry<String, String> tmpEntry = null;
        while (iter.hasNext()) {
            tmpEntry = iter.next();
            sortedMap.put(tmpEntry.getKey(), tmpEntry.getValue());
        }
        return sortedMap;
    }


    public Map<String, Object> scaleCalcMethod(MedicalIndicationDetail medicalIndicationDetail) throws Exception {
        Map<String, Object> scaleCalcResult = new HashMap<>();
        Integer type = medicalIndicationDetail.getType();
        if (type == 2) {
            JSONObject content = medicalIndicationDetail.getContent();
            JSONArray contentDetails = content.getJSONArray("details");
            if ("肾小球滤过率".equals(content.get("name"))) {
                int age = 0;
                double scr = 0.00;
                float k = 0.0f;
                double a = 0.00;
                double denger = 0.00;
                for (int i = 0; i < contentDetails.size(); i++) {
                    JSONObject detailSub = contentDetails.getJSONObject(i);
                    if ("年龄".equals(detailSub.getString("name"))) {
                        if ("".equals(detailSub.getString("value"))) {
                            //如果拿到的年龄为空，
                            break;
                        } else {
                            age = Integer.parseInt(detailSub.getString("value"));
                        }
                    } else if ("血肌酐".equals(detailSub.getString("name"))) {
                        if ("".equals(detailSub.getString("value"))) {
                            //如果给的value是空，给的2.2621是假数据
                            break;
                        } else {
                            if ("umol/L".equals(detailSub.getString("value"))) {
                                scr = Double.valueOf(detailSub.getString("value")) / 88.41;
                            } else {
                                scr = Double.valueOf(detailSub.getString("value"));
                            }
                        }
                    } else if ("性别".equals(detailSub.getString("name"))) {
                        JSONArray genderDetails = detailSub.getJSONArray("details");
                        for (int j = 0; j < genderDetails.size(); j++) {
                            JSONObject genderDetail = genderDetails.getJSONObject(j);
                            //返回的数据结构性别暂时是写死（默认女性）
                            if (genderDetail.getInteger("state") == 1) {
                                if ("男".equals(genderDetail.getString("detailName"))) {
                                    k = 0.9f;
                                    denger = Double.parseDouble(genderDetail.getString("value"));
                                    if (scr <= 0.90) {
                                        a = -0.411;
                                    } else {
                                        a = -1.209;
                                    }
                                } else if ("女".equals(genderDetail.getString("detailName"))) {
                                    k = 0.7f;
                                    denger = Double.parseDouble(genderDetail.getString("value"));
                                    if (scr <= 0.70) {
                                        a = -0.329;
                                    } else {
                                        a = -1.209;
                                    }
                                }
                            }
                        }
                    }
                }
                double eGFR3 = 141 * Math.pow((scr / k), a) * Math.pow(0.993, age) * denger;
                String unit = "ml/min•1.73m2";
                String text = null;
                if (eGFR3 <= 0) {
                    text = "指标值缺少";
                } else if (eGFR3 > 0 && eGFR3 < 15) {
                    text = "肾功能衰竭";
                } else if (eGFR3 >= 15 && eGFR3 <= 29) {
                    text = "重度下降";
                } else if (eGFR3 > 29 && eGFR3 < 60) {
                    text = "中度下降";
                } else if (eGFR3 >= 60 && eGFR3 <= 89) {
                    text = "轻度下降";
                } else if (eGFR3 > 89) {
                    text = "正常或肾损伤代偿期";
                }

                scaleCalcResult.put("text", text);
                scaleCalcResult.put("unit", unit);
                scaleCalcResult.put("value", eGFR3);
                System.out.println("text:" + text + "\tunit:" + unit + "\tvalue:" + eGFR3);
            }
        }


        return scaleCalcResult;
    }
}
