package com.diagbot.facade;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.diagbot.client.BigDataServiceClient;
import com.diagbot.client.GraphServiceClient;
import com.diagbot.client.TranServiceClient;
import com.diagbot.client.bean.FeatureRate;
import com.diagbot.client.bean.GdbResponse;
import com.diagbot.client.bean.Response;
import com.diagbot.client.bean.ResponseData;
import com.diagbot.client.bean.SearchData;
import com.diagbot.dto.PushDTO;
import com.diagbot.dto.PushEMRDTO;
import com.diagbot.dto.PushKYJDTO;
import com.diagbot.dto.QuestionDTO;
import com.diagbot.entity.DeptInfo;
import com.diagbot.entity.DeptVital;
import com.diagbot.entity.QuestionInfo;
import com.diagbot.enums.IsDeleteEnum;
import com.diagbot.enums.LisSourceEnum;
import com.diagbot.enums.QuantitativeTypeEnum;
import com.diagbot.enums.QuestionTypeEnum;
import com.diagbot.exception.CommonErrorCode;
import com.diagbot.exception.CommonException;
import com.diagbot.util.BeanUtil;
import com.diagbot.util.EntityUtil;
import com.diagbot.util.FastJsonUtils;
import com.diagbot.util.ListUtil;
import com.diagbot.util.StringUtil;
import com.diagbot.vo.EMRPushVO;
import com.diagbot.vo.HosCodeVO;
import com.diagbot.vo.LisKYJVO;
import com.diagbot.vo.LisResult;
import com.diagbot.vo.LisResultVO;
import com.diagbot.vo.PushKYJVO;
import com.diagbot.vo.PushVO;
import com.diagbot.vo.QuestionVO;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author:zhaops
 * @time: 2018/11/20 11:18
 */
@Component
public class PushFacade {
    @Autowired
    private BigDataServiceClient bigDataServiceClient;
    @Autowired
    private QuestionFacade questionFacade;
    @Autowired
    private DeptInfoFacade deptInfoFacade;
    @Autowired
    private DeptVitalFacade deptVitalFacade;
    @Autowired
    private TreatmentFacade treatmentFacade;
    @Autowired
    private GraphServiceClient graphServiceClient;
    @Autowired
    private LisMappingFacade lisMappingFacade;
    @Autowired
    private TranServiceClient tranServiceClient;

    /**
     * 推理接口
     *
     * @param pushVO
     * @return
     */
    public ResponseData pushAI(PushVO pushVO) {
        SearchData searchData = new SearchData();
        searchData.setAge(pushVO.getAge());
        searchData.setSymptom(pushVO.getSymptom());
        searchData.setVital(pushVO.getVital());
        searchData.setPacs(pushVO.getPacs());
        searchData.setPast(pushVO.getPast());
        searchData.setOther(pushVO.getOther());
        searchData.setDiag(pushVO.getDiag());
        searchData.setFeatureType(pushVO.getFeatureType());
        searchData.setSysCode("1");
        searchData.setLength(10);

        switch (pushVO.getSex()) {
            case 1:
                searchData.setSex("M");
                break;
            case 2:
                searchData.setSex("F");
                break;
            default:
                searchData.setSex("A");
                break;
        }

        //化验项映射,转公表
        if (pushVO.getLis().size() > 0) {
            Map<String, Map<String, String>> lisConfigMap = lisMappingFacade.getLisMapping_NotEmptyItemName();
            Map<String, String> lisConfigWithEmptyItemNameMap = lisMappingFacade.getLisConfig_EmptyItemName();
            for (LisResultVO lisResultVO : pushVO.getLis()) {
                //source=0 icss页面数据，source=1 外部导入数据，外部导入数据不处理
                if (!lisResultVO.getSource().equals(LisSourceEnum.Inner.getKey())) {
                    continue;
                }
                if (StringUtil.isNotBlank(lisResultVO.getName())) {
                    if (StringUtil.isNotBlank(lisResultVO.getDetailName())) {
                        Map<String, String> detailMap = lisConfigMap.get(lisResultVO.getName());
                        if (StringUtil.isNotBlank(detailMap.get(lisResultVO.getDetailName()))) {
                            lisResultVO.setUniqueName(detailMap.get(lisResultVO.getDetailName()));
                        }
                    } else {
                        lisResultVO.setUniqueName(lisConfigWithEmptyItemNameMap.get(lisResultVO.getName()));
                    }
                }
            }
        }
        List<LisResult> lisResultList = BeanUtil.listCopyTo(pushVO.getLis(), LisResult.class);
        searchData.setLisArr(lisResultList);

        Response<ResponseData> res = bigDataServiceClient.bayesPageData(searchData);
        if (null == res || null == res.getData()) {
            throw new CommonException(CommonErrorCode.SERVER_IS_ERROR, "AI没有返回结果");
        }
        return res.getData();
    }

    /**
     * 推理接口
     *
     * @param pushVO
     * @return
     */
    public PushDTO pushInner(PushVO pushVO, Integer mode) {
        PushDTO pushDTO = new PushDTO();
        ResponseData data = pushAI(pushVO);

        String featureType = pushVO.getFeatureType();
        String[] featureTypes = featureType.split(",|，");
        Set<String> featureTypeSet = new HashSet(Arrays.asList(featureTypes));

        List<FeatureRate> symptom = data.getSymptom();
        List<FeatureRate> dis = data.getDis();
        List<FeatureRate> pacs = data.getPacs();
        List<FeatureRate> labs = data.getLabs();
        List<FeatureRate> other = data.getHistory();
        Map<String, JSONObject> treat = data.getTreat();

        Map<String, Object> symptomMap = list2Map(symptom);
        Map<String, Object> labMap = list2Map(labs);
        Map<String, Object> pacsMap = list2Map(pacs);
        Map<String, Object> otherMap = list2Map(other);

        //症状 标签列表
        if (featureTypeSet.contains(String.valueOf(QuestionTypeEnum.Symptom.getKey()))) {
            //文本模式不推症状，仅结构化模式推症状
            //if (mode.equals(InputModeEnum.Structured.getKey())) {
            List<QuestionDTO> symptomDTO = getTagListByMap(symptomMap, pushVO, QuestionTypeEnum.Symptom.getKey());
            pushDTO.setSymptom(symptomDTO);
            //}
        }
        //其他史 标签列表
        if (featureTypeSet.contains(String.valueOf(QuestionTypeEnum.Other.getKey()))) {
            List<QuestionDTO> otherDTO = getTagListByMap(otherMap, pushVO, QuestionTypeEnum.Other.getKey());
            pushDTO.setOther(otherDTO);
        }
        //查体 返回模板（标签列表）
        if (featureTypeSet.contains(String.valueOf(QuestionTypeEnum.Vital.getKey()))) {
            //没有推送信息时，默认取全科模板
            String deptName = "全科";
            if (dis != null && dis.size() > 0) {
                deptName = dis.get(0).getExtraProperty();
            }
            List<QuestionDTO> vitalDTO = getVitalModule(deptName, pushVO);
            pushDTO.setVital(vitalDTO);

        }
        //化验  标签列表
        if (featureTypeSet.contains(String.valueOf(QuestionTypeEnum.Lis.getKey()))) {
            List<QuestionDTO> labDTO = getTagListByMap(labMap, pushVO, QuestionTypeEnum.Lis.getKey());
            pushDTO.setLab(labDTO);
        }
        //辅检  标签列表
        if (featureTypeSet.contains(String.valueOf(QuestionTypeEnum.Pacs.getKey()))) {
            List<QuestionDTO> pacsDTO = getTagListByMap(pacsMap, pushVO, QuestionTypeEnum.Pacs.getKey());
            pushDTO.setPacs(pacsDTO);
        }
        //诊断 返回分类+标签列表
        if (featureTypeSet.contains(String.valueOf(QuestionTypeEnum.Disease.getKey()))) {
            Map<String, List<QuestionDTO>> disMapDTO = new LinkedHashMap<>();
            Map<String, List<FeatureRate>> disFeatureMap = new LinkedHashMap<>();
            //警惕
            List<String> diseaseNameList = dis.stream().map(disease -> disease.getFeatureName()).collect(Collectors.toList());
            Map<String, String> highRiskMap = new HashMap<>();
            highRiskMap.put("disease", String.join(",", diseaseNameList));
            SearchData searchData = new SearchData();
            searchData.setDiag(String.join(",", diseaseNameList));
            Response<GdbResponse> graphRes = graphServiceClient.highRiskPageData(searchData);
            if (graphRes != null) {
                Map<String, String> graphResult = graphRes.getData().getResult();
                if (graphResult.size() > 0) {
                    Map<String, Object> disMap = new LinkedHashMap<>();
                    for (Map.Entry<String, String> entry : graphResult.entrySet()) {
                        if (entry.getValue().equals("1")) {
                            disMap.put(entry.getKey(), "");
                        }
                    }
                    List<QuestionDTO> disDTO = getTagListByMap(disMap, pushVO, QuestionTypeEnum.Disease.getKey());
                    disMapDTO.put("警惕", disDTO);
                }
            }

            //诊断分类
            for (FeatureRate featureRate : dis) {
                if (StringUtil.isBlank(featureRate.getDesc())) {
                    featureRate.setDesc("{\"可能诊断\":\"\"}");
                }
                Map<String, Object> descMap = FastJsonUtils.getJsonToMap(featureRate.getDesc());
                for (String disClass : descMap.keySet()) {
                    List<FeatureRate> featureRateList = Lists.newLinkedList();
                    if (disFeatureMap.get(disClass) != null) {
                        featureRateList = disFeatureMap.get(disClass);
                    }
                    featureRateList.add(featureRate);
                    disFeatureMap.put(disClass, featureRateList);
                }
            }
            for (Map.Entry<String, List<FeatureRate>> entry : disFeatureMap.entrySet()) {
                Map<String, Object> disMap = list2Map(entry.getValue());
                List<QuestionDTO> disDTO = getTagListByMap(disMap, pushVO, QuestionTypeEnum.Disease.getKey());
                disMapDTO.put(entry.getKey(), disDTO);
            }
            pushDTO.setDis(disMapDTO);
        }
        //治疗方案
        if (featureTypeSet.contains(String.valueOf(QuestionTypeEnum.Drug.getKey()))) {
            if (pushVO.getDiseaseId() == null) {
                throw new CommonException(CommonErrorCode.PARAM_ERROR, "请输入诊断id");
            }
            Map<String, Object> treatmentMap = treatmentFacade.getTreatment(treat, pushVO.getDiseaseId());
            pushDTO.setTreat(treatmentMap);
        }
        return pushDTO;
    }


    /**
     * 获取返回结果标签
     *
     * @param map
     * @param pushVO
     * @param type
     * @return
     */
    public List<QuestionDTO> getTagListByMap(Map<String, Object> map, PushVO pushVO, Integer type) {
        List<QuestionDTO> questionDTOList = Lists.newLinkedList();
        QueryWrapper<QuestionInfo> questionInfoQueryWrapper = new QueryWrapper();
        questionInfoQueryWrapper.eq("is_deleted", IsDeleteEnum.N.getKey()).
                in("tag_name", map.keySet()).
                eq("type", type);
        List<QuestionInfo> questionInfoList = questionFacade.list(questionInfoQueryWrapper);
        Map<String, QuestionInfo> questionMap = EntityUtil.makeEntityMap(questionInfoList, "tagName");
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            QuestionDTO questionDTO = new QuestionDTO();
            if (questionMap.get(entry.getKey()) != null) {
                QuestionVO questionVO = new QuestionVO();
                questionVO.setAge(pushVO.getAge());
                questionVO.setSexType(pushVO.getSex());
                questionVO.setId(questionMap.get(entry.getKey()).getId());
                questionDTO = questionFacade.getById(questionVO);
                if (questionDTO == null || (!questionDTO.getSubType().equals(0))) {
                    questionDTO = new QuestionDTO();
                    questionDTO.setTagName(entry.getKey());
                    questionDTO.setName(entry.getKey());
                }

            } else {
                questionDTO.setTagName(entry.getKey());
                questionDTO.setName(entry.getKey());
            }
            questionDTOList.add(questionDTO);
        }
        return questionDTOList;
    }

    /**
     * 推理接口-快易检
     *
     * @param pushKYJVO
     * @return
     */
    public PushKYJDTO pushKYJ(PushKYJVO pushKYJVO) {
        PushVO pushVO = new PushVO();
        pushVO.setAge(pushKYJVO.getAge());
        pushVO.setSex(pushKYJVO.getSex());
        pushVO.setFeatureType(pushKYJVO.getFeatureType());

        //参数预处理
        /*String lis = "";
        List<String> lisResultList = Lists.newArrayList();
        for (LisKYJVO lisKYJVO : pushKYJVO.getLisResultList()) {
            lisKYJVO = resultCalculation(lisKYJVO);
            lisResultList.addAll(getLisInputs(lisKYJVO));
        }
        lis = String.join(",", lisResultList);
        pushVO.setLis(lis);*/

        //化验结果
        List<LisResultVO> lisResultVOList = BeanUtil.listCopyTo(pushKYJVO.getLisResultList(), LisResultVO.class);
        for (LisResultVO lisResultVO : lisResultVOList) {
            lisResultVO.setSource(LisSourceEnum.Outer.getKey());
        }
        pushVO.setLis(lisResultVOList);

        ResponseData responseData = pushAI(pushVO);
        PushKYJDTO pushKYJDTO = new PushKYJDTO();
        pushKYJDTO.setLabs(responseData.getLabs());
        pushKYJDTO.setDis(responseData.getDis());
        return pushKYJDTO;
    }

    /**
     * 将list 转换成 map
     *
     * @param list
     * @return
     */
    public Map<String, Object> list2Map(List<FeatureRate> list) {
        Map<String, Object> map = new LinkedHashMap<>();
        for (FeatureRate featureRate : list) {
            map.put(featureRate.getFeatureName(), null);
        }
        return map;
    }


    /**
     * 快易检结果预处理
     *
     * @param lisKYJVO
     * @return
     */
    public LisKYJVO resultCalculation(LisKYJVO lisKYJVO) {
        if (lisKYJVO.getValue() != null) {
            if (lisKYJVO.getMaxValue() != null) {
                Integer comResult = lisKYJVO.getValue().compareTo(lisKYJVO.getMaxValue());
                if (comResult > 0) {
                    lisKYJVO.setMultipleState(QuantitativeTypeEnum.Up.getName());
                    if (!lisKYJVO.getMaxValue().equals(0.0)) {
                        lisKYJVO.setMultipleValue(lisKYJVO.getValue() / lisKYJVO.getMaxValue());
                    }
                }
            }
            if (lisKYJVO.getMinValue() != null) {
                Integer comResult = lisKYJVO.getValue().compareTo(lisKYJVO.getMinValue());
                if (comResult < 0) {
                    lisKYJVO.setMultipleState(QuantitativeTypeEnum.Down.getName());
                    if (!lisKYJVO.getMinValue().equals(0.0)) {
                        lisKYJVO.setMultipleValue(lisKYJVO.getValue() / lisKYJVO.getMinValue());
                    }
                }
            }
            if (StringUtil.isBlank(lisKYJVO.getMultipleState())) {
                lisKYJVO.setMultipleState(QuantitativeTypeEnum.Normal.getName());
            }
        }
        return lisKYJVO;
    }

    /**
     * 拼接化验项的文本结果
     *
     * @param lisKYJVO
     * @return
     */
    public List<String> getLisInputs(LisKYJVO lisKYJVO) {
        List<String> stringList = Lists.newArrayList();
        if (StringUtil.isBlank(lisKYJVO.getName())) {
            return stringList;
        } else if (lisKYJVO.getValue() != null) {
            //数值
            String lisText = lisKYJVO.getName() + "," + lisKYJVO.getValue() + " " + lisKYJVO.getUnits();
            stringList.add(lisText);
            //倍数
            if (StringUtil.isBlank(lisKYJVO.getMultipleState())) {
                lisText = lisKYJVO.getName() + "," + lisKYJVO.getMultipleState() + " " + lisKYJVO.getMultipleValue();
                stringList.add(lisText);
            }
        } else if (StringUtil.isBlank(lisKYJVO.getOtherValue())) {
            //阴性阳性和其他文字描述
            String lisText = lisKYJVO.getName() + "," + lisKYJVO.getOtherValue();
            stringList.add(lisText);
        }
        return stringList;
    }

    /**
     * 获取查体模板
     *
     * @param deptName
     * @param pushVO
     * @return
     */
    public List<QuestionDTO> getVitalModule(String deptName, PushVO pushVO) {
        List<QuestionDTO> vitalDTO = Lists.newLinkedList();
        QueryWrapper<DeptInfo> deptInfoQueryWrapper = new QueryWrapper<>();
        deptInfoQueryWrapper.eq("is_deleted", IsDeleteEnum.N.getKey()).
                eq("name", deptName);
        DeptInfo deptInfo = deptInfoFacade.getOne(deptInfoQueryWrapper);
        if (deptInfo == null) {
            //科室信息不存在时推全科模板
            deptName = "全科";
            deptInfoQueryWrapper = new QueryWrapper<>();
            deptInfoQueryWrapper.eq("is_deleted", IsDeleteEnum.N.getKey()).
                    eq("name", deptName);
            deptInfo = deptInfoFacade.getOne(deptInfoQueryWrapper);
            if (deptInfo == null) {
                throw new CommonException(CommonErrorCode.NOT_EXISTS, "全科信息未维护");
            }
        }

        QueryWrapper<DeptVital> deptVitalQueryWrapper = new QueryWrapper<>();
        deptVitalQueryWrapper.eq("is_deleted", IsDeleteEnum.N.getKey()).
                eq("dept_id", deptInfo.getId()).
                orderByAsc("order_no");
        List<DeptVital> deptVitalList = deptVitalFacade.list(deptVitalQueryWrapper);
        //科室模板为空时，取全科模板
        if (deptVitalList.size() == 0) {
            deptVitalQueryWrapper = new QueryWrapper<>();
            String sql = "select id from icss_dept_info where name='全科' and is_deleted='N'";
            deptVitalQueryWrapper.eq("is_deleted", IsDeleteEnum.N.getKey()).
                    inSql("dept_id", sql).
                    orderByAsc("order_no");
            deptVitalList = deptVitalFacade.list(deptVitalQueryWrapper);
        }
        //标签列表
        for (DeptVital deptVital : deptVitalList) {
            QuestionVO questionVO = new QuestionVO();
            questionVO.setAge(pushVO.getAge());
            questionVO.setSexType(pushVO.getSex());
            questionVO.setId(deptVital.getVitalId());
            QuestionDTO questionDTO = questionFacade.getById(questionVO);
            if (questionDTO != null) {
                vitalDTO.add(questionDTO);
            }
        }
        return vitalDTO;
    }

    /**
     * 电子病历评级-数据服务模式推理
     *
     * @param emrPushVO
     * @return
     */
    public PushEMRDTO pushEMR(EMRPushVO emrPushVO) {
        Boolean isDocking = tranServiceClient.isDocking().data;
        PushEMRDTO pushEMRDTO = new PushEMRDTO();
        HosCodeVO hosCodeVO = new HosCodeVO();
        hosCodeVO.setHosCode(emrPushVO.getHosCode());
        PushVO pushVO = new PushVO();
        BeanUtil.copyProperties(emrPushVO, pushVO);
        //化验项转公表内容,参数处理
        if (ListUtil.isNotEmpty(pushVO.getLis())) {
            Map<String, Map<String, String>> lisConfigMap = new LinkedHashMap<>();
            Map<String, String> lisConfigMap_emptyItemName = new LinkedHashMap<>();
            if (isDocking) {
                lisConfigMap = tranServiceClient.getLisConfigByHosCode_NotEmptyItemName(hosCodeVO).data;
                lisConfigMap_emptyItemName = tranServiceClient.getLisConfigByHosCode_EmptyItemName(hosCodeVO).data;
            } else {
                lisConfigMap = lisMappingFacade.getLisMapping_NotEmptyItemName();
                lisConfigMap_emptyItemName = lisMappingFacade.getLisConfig_EmptyItemName();
            }
            List<LisResultVO> lisResultVOList = pushVO.getLis();
            for (LisResultVO lisResultVO : lisResultVOList) {
                if (StringUtil.isNotBlank(lisResultVO.getName())) {
                    if (StringUtil.isNotBlank(lisResultVO.getDetailName())) {
                        lisResultVO.setUniqueName(lisConfigMap.get(lisResultVO.getName()).get(lisResultVO.getDetailName()));
                    } else {
                        lisResultVO.setUniqueName(lisConfigMap_emptyItemName.get(lisResultVO.getName()));
                    }
                }
            }
            pushVO.setLis(lisResultVOList);
        }
        ResponseData data = pushAI(pushVO);
        String featureType = pushVO.getFeatureType();
        String[] featureTypes = featureType.split(",|，");
        Set<String> featureTypeSet = new HashSet(Arrays.asList(featureTypes));

        if (featureTypeSet.contains(String.valueOf(QuestionTypeEnum.Lis.getKey()))) {
            List<FeatureRate> labs = data.getLabs();
            if (labs.size() > 0) {
                List<String> lisList = labs.stream().map(lab -> lab.getFeatureName()).collect(Collectors.toList());
                pushEMRDTO.setLisList(lisList);
            }
        }
        if (featureTypeSet.contains(String.valueOf(QuestionTypeEnum.Pacs.getKey()))) {
            List<FeatureRate> pacsFeatures = data.getPacs();
            if (pacsFeatures.size() > 0) {
                List<String> pacsList = pacsFeatures.stream().map(pacs -> pacs.getFeatureName()).collect(Collectors.toList());
                pushEMRDTO.setPacsList(pacsList);
            }
        }
        if (featureTypeSet.contains(String.valueOf(QuestionTypeEnum.Disease.getKey()))) {
            List<FeatureRate> dis = data.getDis();
            List<String> disNameList = dis.stream().map(disease -> disease.getFeatureName()).collect(Collectors.toList());
            Map<String, List<String>> retDisMap = new LinkedHashMap<>();
            Map<String, String> disMap = tranServiceClient.getDiseaseIcdByHosCode(hosCodeVO).data;

            //诊断分类
            for (FeatureRate featureRate : dis) {
                if (StringUtil.isBlank(featureRate.getDesc())) {
                    featureRate.setDesc("{\"可能诊断\":\"\"}");
                }
                Map<String, Object> descMap = FastJsonUtils.getJsonToMap(featureRate.getDesc());
                for (String disClass : descMap.keySet()) {
                    List<String> retDisList = Lists.newLinkedList();
                    if (retDisMap.get(disClass) != null) {
                        retDisList = retDisMap.get(disClass);
                    }
                    if (isDocking) {
                        //对接模式转icd10名称
                        retDisList.add(disMap.get(featureRate.getFeatureName()));
                    } else {
                        retDisList.add(featureRate.getFeatureName());
                    }
                    retDisMap.put(disClass, retDisList);
                }
            }
            //警惕
            SearchData searchData = new SearchData();
            searchData.setDiag(String.join(",", disNameList));
            Response<GdbResponse> graphRes = graphServiceClient.highRiskPageData(searchData);
            Map<String, String> graphResult = graphRes.getData().getResult();
            if (graphResult.size() > 0) {
                List<String> highRiskDisList = Lists.newLinkedList();
                for (Map.Entry<String, String> entry : graphResult.entrySet()) {
                    if (entry.getValue().equals("1")) {
                        if (isDocking) {
                            highRiskDisList.add(disMap.get(entry.getKey()));
                        } else {
                            highRiskDisList.add(entry.getKey());
                        }
                    }
                }
                retDisMap.put("警惕", highRiskDisList);
            }
            pushEMRDTO.setDis(retDisMap);
        }
        return pushEMRDTO;
    }
}