package org.diagbot.push.controller;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.diagbot.bigdata.work.AlgorithmCore;
import org.diagbot.bigdata.work.ResultDataProxy;
import org.diagbot.common.push.bean.CrisisDetail;
import org.diagbot.common.push.bean.FeatureRate;
import org.diagbot.common.push.bean.ResponseData;
import org.diagbot.common.push.bean.SearchData;
import org.diagbot.common.push.bean.neo4j.Drugs;
import org.diagbot.common.push.bean.neo4j.Filnlly;
import org.diagbot.common.push.bean.neo4j.MedicalIndication;
import org.diagbot.common.push.bean.neo4j.MedicalIndicationDetail;
import org.diagbot.common.push.bean.neo4j.Medicition;
import org.diagbot.common.push.cache.CacheUtil;
import org.diagbot.common.push.filter.ClassifyDiag;
import org.diagbot.common.push.filter.rule.PretreatmentRule;
import org.diagbot.common.push.work.ParamsDataProxy;
import org.diagbot.graphWeb.work.GraphCalculate;
import org.diagbot.graphWeb.work.LisPacsCalculate;
import org.diagbot.nlp.rule.pretreat.Pretreatment;
import org.diagbot.nlp.rule.pretreat.PretreatmentLis;
import org.diagbot.nlp.util.Constants;
import org.diagbot.nlp.util.NlpCache;
import org.diagbot.pub.api.Response;
import org.diagbot.pub.jdbc.MysqlJdbc;
import org.diagbot.pub.utils.PropertiesUtil;
import org.diagbot.pub.utils.http.HttpApi;
import org.diagbot.pub.web.BaseController;
import org.diagbot.rule.crisis.CrisisApplication;
import org.diagbot.rule.lis.LisApplication;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

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

/**
 * @ClassName org.diagbot.push.controller.AlgorithmController
 * @Description TODO
 * @Author fyeman
 * @Date 2019/1/16/016 19:00
 * @Version 1.0
 **/
@Controller
@RequestMapping("/algorithm")
public class AlgorithmController extends BaseController {
    Logger logger = LoggerFactory.getLogger(AlgorithmController.class);

    {
        listView = "/pages/algorithm/list.html";
    }

    @RequestMapping({ "/index" })
    public String index() {
        return listView;
    }

    @RequestMapping(value = "/page_neural")
    @ResponseBody
    public Response<ResponseData> neuralData(HttpServletRequest request, SearchData searchData) throws Exception {
        return combine(request, searchData);
    }

    @RequestMapping(value = "/neural", method = RequestMethod.POST)
    @ResponseBody
    public Response<ResponseData> bayesPageData(HttpServletRequest request, @RequestBody SearchData searchData) throws Exception {
        return combine(request, searchData);
    }

    @RequestMapping(value = "/validate")
    @ResponseBody
    public Response<ResponseData> validate(HttpServletRequest request) throws Exception {
        Response<ResponseData> response = new Response<>();

        MysqlJdbc nlpJdbc = new MysqlJdbc("root", "diagbot@20180822", "jdbc:mysql://192.168.2.235:3306/med-s?useUnicode=true&characterEncoding=UTF-8");
        List<Map<String, String>> data = nlpJdbc.query("doc_info", new String[] { "pk_dcpv", "present", "diag", "sex", "age" }, "");

        Map<String, String> diags = NlpCache.getStandard_info_synonym_map().get(Constants.word_property_diagnose);

        List<Map<String, Object>> updates = new ArrayList<>();
        List<Map<String, Object>> wheres = new ArrayList<>();
        for (Map<String, String> map : data) {
            SearchData searchData = new SearchData();
//            searchData.setAge(Integer.parseInt(map.get("age")));
//            searchData.setSex(map.get("sex"));
            searchData.setSymptom(map.get("present"));
            searchData.setFeatureType("2");
            searchData.setSysCode("2");


            Response<ResponseData> rs = combine(request, searchData);
            List<FeatureRate> featureRates = rs.getData().getDis();

            Map<String, Object> line = new HashMap<>();
            Map<String, Object> where = new HashMap<>();

            String push_diag = "";
            for (int i = 0; i < featureRates.size(); i++) {
                FeatureRate fr = featureRates.get(i);
                if ((fr.getFeatureName().equals(map.get("diag")) || fr.getFeatureName().equals(diags.get(map.get("diag")))) && i < 3) {
                    line.put("check_3", "1");
                } else if ((fr.getFeatureName().equals(map.get("diag")) || fr.getFeatureName().equals(diags.get(map.get("diag")))) && i < 5) {
                    line.put("check_5", "1");
                }
                if (i > 0 && i < 10) {
                    push_diag = push_diag + "," + fr.getFeatureName();
                } else if (i == 0) {
                    push_diag = fr.getFeatureName();
                }
            }
            line.put("push_diag", push_diag);
            where.put("pk_dcpv", map.get("pk_dcpv"));

            updates.add(line);
            wheres.add(where);
        }

        nlpJdbc.update("doc_info", updates, wheres);

        return response;
    }

    public Response<ResponseData> combine(HttpServletRequest request, SearchData searchData) throws Exception {
        ResponseData responseData = new ResponseData();
        logger.info("开始推送服务......");
        LisApplication lisApplication = new LisApplication();
        if ((searchData.getLisArr() == null || searchData.getLisArr().size() == 0)
                && StringUtils.isNotEmpty(searchData.getLis())) {
            Pretreatment pretreatment = new PretreatmentLis();
            searchData.setLisArr(pretreatment.analyze(searchData.getLis()));
        }
        lisApplication.lisConvertToInputs(searchData.getLisArr(),searchData);

        Response<ResponseData> response = new Response();
        //一些基本信息预处理 如年龄 性别
        ParamsDataProxy paramsDataProxy = new ParamsDataProxy();
        paramsDataProxy.createNormalInfo(searchData);
        //数据预处理
        PretreatmentRule pretreatmentRule = new PretreatmentRule();
        pretreatmentRule.rule(searchData);
        //危机值
        CrisisApplication crisisApplication = new CrisisApplication();
        responseData.setCrisisDetails(crisisApplication.crisisContent(searchData));

        //大数据推送
        AlgorithmCore core = new AlgorithmCore();
        ResponseData bigDataResponseData = core.algorithm(request, searchData, responseData);

        GraphCalculate graphCalculate = new GraphCalculate();
        ResponseData graphResponseData = graphCalculate.calculate(request, searchData);
        if (graphResponseData.getDis().size() > 0) {
            List<FeatureRate> disFeatureRates = new ArrayList<>();
            /*boolean isFind = false;
            for (int i = 0; i < bigDataResponseData.getDis().size(); i++) {
                FeatureRate bigdata_fr = bigDataResponseData.getDis().get(i);
                isFind = false;
                for (FeatureRate graph_fr : graphResponseData.getDis()) {
                    if (graph_fr.getDesc().contains("拟诊")|| graph_fr.getDesc().contains("确诊") && bigdata_fr.getFeatureName().equals(graph_fr.getFeatureName())) {
                        isFind = true;
                    }
                }
                if (!isFind) {
                    disFeatureRates.add(bigdata_fr);
                }
            }*/
            List<FeatureRate> bigdis = bigDataResponseData.getDis();
            List<FeatureRate> graphdis = graphResponseData.getDis();
            for (FeatureRate bg:graphdis) {
                Iterator<FeatureRate> iterator = bigdis.iterator();
                while (iterator.hasNext()){
                    FeatureRate gd = iterator.next();
                    if(gd.getFeatureName().equals(bg.getFeatureName()) &&(bg.getDesc().contains("确诊")|| bg.getDesc().contains("拟诊"))){
                        iterator.remove();
                    }
                }
            }
            disFeatureRates = bigdis;
            List<FeatureRate> graphFeatureRates = graphResponseData.getDis();
            graphFeatureRates.addAll(disFeatureRates);
            bigDataResponseData.setDis(graphFeatureRates);
        }
        //归一之前诊断信息
        bigDataResponseData.setBeforeCombineDis(bigDataResponseData.getDis());
        //推送出的诊断信息作为参数传入知识图谱
        List<FeatureRate> pushDiags = new ArrayList<>();
        pushDiags.addAll(bigDataResponseData.getDis());
        searchData.setPushDiags(pushDiags);
        bigDataResponseData.setTreat(graphResponseData.getTreat());

        //量表和指标推送
        Map<String, List<CrisisDetail>> crisisDetails = responseData.getCrisisDetails();
        List<MedicalIndication> crisisDetailsList = this.getCrisisDetails(crisisDetails);
        List<MedicalIndication> medicalIndications = graphResponseData.getMedicalIndications();
        if (medicalIndications == null) {
            medicalIndications = new ArrayList<>();
        }
        medicalIndications.addAll(crisisDetailsList);
        if (medicalIndications != null && medicalIndications.size() > 0) {
            logger.info("指标推送!!!!!!!!!");
            //           bigDataResponseData.getMedicalIndications().addAll(medicalIndications);
            bigDataResponseData.setMedicalIndications(medicalIndications);
        }

        //推送管理评估
        bigDataResponseData.setManagementEvaluation(graphResponseData.getManagementEvaluation());
        //知识图谱直接替换大数据中的检验检查数据
        LisPacsCalculate lisPacsCalculate = new LisPacsCalculate();
        graphResponseData = lisPacsCalculate.getLisPacs(request, searchData);

        bigDataResponseData.setLabs(graphResponseData.getLabs());
        bigDataResponseData.setPacs(graphResponseData.getPacs());

        //体征结果和指标推送
        Map<String, String> vitalCache = CacheUtil.getVitalCache();
        List<String> featureList = Arrays.asList(searchData.getFeatureTypes());
        List<FeatureRate> vitals = graphResponseData.getVitals();
        if (featureList.contains(Constants.feature_type_vital_index) && this.getVital(vitalCache, vitals).size() > 0) {
            bigDataResponseData.setVitals(this.getVital(vitalCache, vitals));

        }
        if (featureList.contains(Constants.feature_type_vital) && vitals.size() > 0) {
            bigDataResponseData.setVitals(vitals);
        }

        //把所有的诊断拿出来经过过滤层过滤
        ClassifyDiag classifyDiag = new ClassifyDiag();
        List<FeatureRate> upfes = classifyDiag.filterDiag(graphResponseData, pushDiags);
        List<FeatureRate> classify = classifyDiag.diagClassify(upfes);
        List<FeatureRate> featureRates = classifyDiag.sortDiag(classify);
        bigDataResponseData.setDis(featureRates);
        //返回结果化验、辅检、体征、进行性别年龄过滤
        ResultDataProxy resultDataProxy = new ResultDataProxy();
        resultDataProxy.resultSexAgeFilter(request, bigDataResponseData, searchData);
        response.setData(bigDataResponseData);
        return response;
    }

    /**
     * 包装输出的危急值
     *
     * @param crisisDetails
     * @return
     */
    public List<MedicalIndication> getCrisisDetails(Map<String, List<CrisisDetail>> crisisDetails) {
        List<MedicalIndication> crisisDetailList = new ArrayList<>();
        for (Map.Entry<String, List<CrisisDetail>> entry : crisisDetails.entrySet()) {
            for (CrisisDetail crisisDetail : entry.getValue()) {
                String originText = crisisDetail.getOriginText();//文本输入的数据
                String remindText = crisisDetail.getRemindText();//危机警示指标
                String standardText = crisisDetail.getStandardText();//评判标准
                if (StringUtils.isNotEmpty(remindText)) {
                    MedicalIndication medicalIndication = new MedicalIndication();
                    List<MedicalIndicationDetail> crisisMid = new ArrayList<>();
                    MedicalIndicationDetail medicalIndicationDetail = new MedicalIndicationDetail();
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("controlType", 2);
                    jsonObject.put("name", standardText);
                    medicalIndicationDetail.setType(4);
                    medicalIndicationDetail.setContent(jsonObject);
                    crisisMid.add(medicalIndicationDetail);
                    medicalIndication.setName(remindText);
                    medicalIndication.setDetails(crisisMid);
                    crisisDetailList.add(medicalIndication);
                }
            }
        }
        return crisisDetailList;
    }

    public List<FeatureRate> getVital(Map<String, String> vitalCache, List<FeatureRate> vitals) {
        Set<String> vitalSet = new LinkedHashSet<>();
        List<FeatureRate> vitalList = new ArrayList<>();
        if (vitals != null) {
            for (FeatureRate f : vitals) {
                String s = vitalCache.get(f.getFeatureName());
                if (StringUtils.isNotEmpty(s)) {
                    vitalSet.add(s);
                }
            }
        }
        if (vitalSet != null) {
            for (String vi : vitalSet) {
                FeatureRate featureRate = new FeatureRate();
                featureRate.setFeatureName(vi);
                vitalList.add(featureRate);
            }
        }
        return vitalList;
    }

    public Response<ResponseData> algorithm(HttpServletRequest request, SearchData searchData) throws Exception {
        Response<ResponseData> response = new Response();

        PropertiesUtil propertiesUtil = new PropertiesUtil("push.properties");
        //大数据推送
        HttpApi<Response> api = new HttpApi<Response>();
        // 根据hospitalCode从his获取所有疾病库信息
        Response bigDataResponse = api.doPost(propertiesUtil.getProperty("bigdata.http.url"), searchData,
                Response.class);
        LinkedHashMap bigDataLinkedHashMap = (LinkedHashMap) bigDataResponse.getData();
        //转FeatureRate对象
        ResponseData bigDataResponseData = map2ResponseData(bigDataLinkedHashMap);
        //入参信息
        bigDataResponseData = addInputs(bigDataResponseData, bigDataLinkedHashMap);
        //知识图谱推送
        Response graphResponse = api.doPost(propertiesUtil.getProperty("graph.http.url"), searchData,
                Response.class);
        LinkedHashMap graphLinkedHashMap = (LinkedHashMap) graphResponse.getData();
        //转FeatureRate对象
        ResponseData graphResponseData = map2ResponseData(graphLinkedHashMap);
        //添加治疗信息
        graphResponseData = addTreat(graphResponseData, graphLinkedHashMap);
        if (graphResponseData.getDis().size() > 0) {
            List<FeatureRate> disFeatureRates = new ArrayList<>();
            boolean isFind = false;
            for (int i = 0; i < bigDataResponseData.getDis().size(); i++) {
                FeatureRate bigdata_fr = bigDataResponseData.getDis().get(i);
                isFind = false;
                for (FeatureRate graph_fr : graphResponseData.getDis()) {
                    if (bigdata_fr.getFeatureName().equals(graph_fr.getFeatureName())) {
                        isFind = true;
                    }
                }
                if (!isFind) {
                    disFeatureRates.add(bigdata_fr);
                }
            }
            List<FeatureRate> graphFeatureRates = graphResponseData.getDis();
            graphFeatureRates.addAll(disFeatureRates);
            //大数据推送疾病数据用知识图谱替换
            bigDataResponseData.setDis(graphFeatureRates);
        }
        bigDataResponseData.setTreat(graphResponseData.getTreat());
        response.setData(bigDataResponseData);
        return response;
    }

    private ResponseData map2ResponseData(LinkedHashMap linkedHashMap) {
        ResponseData responseData = new ResponseData();
        if (linkedHashMap.get("dis") != null) {
            responseData.setDis(map2FeatureRates((List<LinkedHashMap<String, String>>) linkedHashMap.get("dis")));
        }
        if (linkedHashMap.get("symptom") != null) {
            responseData.setSymptom(map2FeatureRates((List<LinkedHashMap<String, String>>) linkedHashMap.get("symptom")));
        }
        if (linkedHashMap.get("vitals") != null) {
            responseData.setVitals(map2FeatureRates((List<LinkedHashMap<String, String>>) linkedHashMap.get("vitals")));
        }
        if (linkedHashMap.get("labs") != null) {
            responseData.setLabs(map2FeatureRates((List<LinkedHashMap<String, String>>) linkedHashMap.get("labs")));
        }
        if (linkedHashMap.get("pacs") != null) {
            responseData.setPacs(map2FeatureRates((List<LinkedHashMap<String, String>>) linkedHashMap.get("pacs")));
        }
        return responseData;
    }

    private List<FeatureRate> map2FeatureRates(List<LinkedHashMap<String, String>> data) {
        List<FeatureRate> featureRates = new ArrayList<>();
        for (LinkedHashMap<String, String> map : data) {
            FeatureRate fr = new FeatureRate();
            fr.setFeatureName(map.get("featureName"));
            fr.setRate(map.get("rate"));
            fr.setExtraProperty(map.get("extraProperty"));
            featureRates.add(fr);
        }
        return featureRates;
    }

    private ResponseData addInputs(ResponseData bigDataResponseData, LinkedHashMap linkedHashMap) {
        if (linkedHashMap.get("inputs") != null) {
            bigDataResponseData.setInputs((Map<String, Map<String, String>>) linkedHashMap.get("inputs"));
        }
        return bigDataResponseData;
    }

    private ResponseData addTreat(ResponseData graphResponseData, LinkedHashMap linkedHashMap) {
        Map<String, Filnlly> treatResult = new HashMap<String, Filnlly>();
        if (linkedHashMap.get("treat") != null) {
            LinkedHashMap<String, LinkedHashMap<String, ArrayList<LinkedHashMap>>> data = (LinkedHashMap<String, LinkedHashMap<String, ArrayList<LinkedHashMap>>>) linkedHashMap.get("treat");
            for (Map.Entry<String, LinkedHashMap<String, ArrayList<LinkedHashMap>>> fd : data.entrySet()) {
                String diseaseName = fd.getKey();
                LinkedHashMap<String, ArrayList<LinkedHashMap>> value = fd.getValue();
                ArrayList<LinkedHashMap> treament = value.get("treatment");
                ArrayList<Drugs> drugsList = new ArrayList<Drugs>();
                for (LinkedHashMap sd : treament) {
                    //创建药类对象,对药类对象进行封装
                    Drugs drugs = new Drugs();

                    String bigdrugsName = String.valueOf(sd.get("bigdrugsName"));
                    String subdrugsName = String.valueOf(sd.get("subdrugsName"));
                    int drugsForbidden = Integer.parseInt(sd.get("drugsForbidden").toString());
                    ArrayList<LinkedHashMap<String, Object>> medicitionsList = (ArrayList<LinkedHashMap<String, Object>>) sd.get("medicitionsList");
                    LinkedList<Medicition> medicitionObjectList = new LinkedList<>();
                    for (LinkedHashMap<String, Object> ds : medicitionsList) {
                        //创建药对象,进行封装
                        Medicition medicitionObject = new Medicition();

                        String medicitionName = String.valueOf(ds.get("medicitionName"));
                        String rate = String.valueOf(ds.get("rate"));
                        Integer isShow = Integer.parseInt(ds.get("isShow").toString());
                        Integer forbidden = Integer.parseInt(ds.get("forbidden").toString());
                        medicitionObject.setMedicitionName(medicitionName);//设置药名
                        medicitionObject.setRate(rate);//设置药的使用率
                        medicitionObject.setIsShow(isShow);//设置这个药是否展示
                        medicitionObject.setForbidden(forbidden);//设置这个药是否为禁忌药
                        medicitionObjectList.add(medicitionObject);
                    }
                    drugs.setBigdrugsName(bigdrugsName);//药的大类
                    drugs.setSubdrugsName(subdrugsName);//药的子类
                    drugs.setDrugsForbidden(drugsForbidden);
                    drugs.setMedicitionsList(medicitionObjectList);//这个类所包含的药物列表
                    drugsList.add(drugs);//药类列表
                }
                Filnlly filnlly = new Filnlly();
                filnlly.setTreatment(drugsList);
                treatResult.put(diseaseName, filnlly);
            }
        }
        graphResponseData.setTreat(treatResult);
        return graphResponseData;
    }
}
