package cn.sh.stc.sict.theme.hphy.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.sh.stc.sict.cloud.common.core.constant.Constant;
import cn.sh.stc.sict.cloud.common.core.util.NumberUtil;
import cn.sh.stc.sict.cloud.common.core.util.R;
import cn.sh.stc.sict.theme.hphy.constant.PatientConstant;
import cn.sh.stc.sict.theme.hphy.dao.HphyGuideRecordMapper;
import cn.sh.stc.sict.theme.hphy.model.HphyGuideRecord;
import cn.sh.stc.sict.theme.hphy.model.HphyPatientBase;
import cn.sh.stc.sict.theme.hphy.service.HphyDoctorService;
import cn.sh.stc.sict.theme.hphy.service.HphyGuideRecordService;
import cn.sh.stc.sict.theme.hphy.service.HphyPatientBaseService;
import cn.sh.stc.sict.theme.hphy.util.PythonUtil;
import cn.sh.stc.sict.theme.hphy.vo.DiseaseAnalysisDTO;
import cn.sh.stc.sict.theme.hphy.vo.DoctorMatchVO;
import cn.sh.stc.sict.theme.hphy.vo.PythonDTO;
import cn.sh.stc.sict.theme.hphy.vo.PythonResult;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;


@Service("hphyGuideRecordService")
@AllArgsConstructor
public class HphyGuideRecordServiceImpl extends ServiceImpl<HphyGuideRecordMapper, HphyGuideRecord> implements HphyGuideRecordService {

    private final HphyGuideRecordMapper hphyGuideRecordMapper;
    private final HphyDoctorService hphyDoctorService;
    private final HphyPatientBaseService hphyPatientBaseService;

    /**
     * 初始化导医记录
     *
     * @param patient
     * @return
     */
    @Override
    public HphyGuideRecord initGuide(HphyPatientBase patient) {
        HphyGuideRecord record = new HphyGuideRecord();
        record.setPatientId(patient.getId());
        record.setPatientName(patient.getName());
        this.saveOrUpdate(record);
        return record;
    }


    /**
     * 疾病判断
     *
     * @param guideId
     * @return
     */
    @Override
    public R analysisDisease(Long patientId, Long guideId) throws UnsupportedEncodingException {
        // 调用python程序分析
        HphyGuideRecord guide = this.getById(guideId);
        if (null == guide || NumberUtil.isNullOrZero(guide.getId())) {
            return new R().error("未找到导医记录!");
        }
        List<DiseaseAnalysisDTO> dtoList = hphyGuideRecordMapper.listAnalysis(guideId);
        Map<String, List<DiseaseAnalysisDTO>> map = dtoList.stream().collect(Collectors.groupingBy(DiseaseAnalysisDTO::getQuestionTag));
        // 高血压 -> 高血压分级 -> 心血管危险程度分层
        // drug 0 1
        boolean drug = this.getDrug(null, map);
        // disease_level 0 1 2 3
        int diseaseLevel = this.getLevel(null, map);
        if (diseaseLevel == 0 && !drug) {
            PythonDTO pydto = new PythonDTO();
            pydto.setResult("您的血压值在正常范围内，身体若有不适请到当地医院做详细检查以明确诊断！");
            return new R(pydto).setBizCode(100);
        }
        String riskLevel = this.getRiskLevel(null, diseaseLevel, map);
        // 2020/10/16 吴健人-》 去掉心血管分层
        riskLevel = "";
        // 症状
        List<String> disease = new ArrayList<>();
        String tt = "高血压" + (diseaseLevel > 0 ? (diseaseLevel + "级" + riskLevel) : "");
        disease.add(tt);
        if (map.containsKey(PatientConstant.QUESTION_SYMPTOM)) {
            map.get(PatientConstant.QUESTION_SYMPTOM).forEach(d -> {
                disease.add(d.getAnswer());
            });
        }
        if (map.containsKey(PatientConstant.QUESTION_DIAB)) {
            if (Constant.STRING_YES.equals(map.get(PatientConstant.QUESTION_DIAB).get(0).getAnswerTag())) {
                disease.add("糖尿病");
            }
        }
        // 存储疾病判断结果
        HphyGuideRecord update = new HphyGuideRecord();
        update.setId(guideId);
        update.setDisease(disease.toString());
        update.setRiskLevel(riskLevel);

        HphyPatientBase patient = hphyPatientBaseService.getById(patientId);
        PythonDTO pydto = new PythonDTO(patient, disease);
        String pyResutl = PythonUtil.getDcotorMatchListForHP(JSONUtil.toJsonStr(pydto));
        update.setPyResult(pyResutl);
        update.setAge(patient.getAge());
        this.updateById(update);
        JSONObject obj = JSONUtil.parseObj(pyResutl);
        // indicator 0-字符串 1-json
        if (Constant.STRING_YES.equals(obj.getStr("indicator"))) {
            List<PythonResult> pythonList = JSON.parseArray(obj.getStr("data"), PythonResult.class);
            List<DoctorMatchVO> resultList = hphyDoctorService.getRecommendList(guide, pythonList);
            pydto.setResult(resultList);
            return new R(pydto).setBizCode(200);
        } else {
            pydto.setResult(obj.getStr("data"));
            this.updateById(update);
            return new R(pydto).setBizCode(100);
        }
    }

    /**
     * 数据分析，疾病判断 ==》 返回分析结果
     *
     * @param patientId
     * @param guideId
     * @return
     */
    @Override
    public List<DiseaseAnalysisDTO> analysisDiseaseV2(Long patientId, Long guideId) throws UnsupportedEncodingException {
        List<DiseaseAnalysisDTO> resultList = new ArrayList<>();
        List<DiseaseAnalysisDTO> dtoList = hphyGuideRecordMapper.listAnalysis(guideId);
        Map<String, List<DiseaseAnalysisDTO>> map = dtoList.stream().collect(Collectors.groupingBy(DiseaseAnalysisDTO::getQuestionTag));
        // 高血压 -> 高血压分级 -> 心血管危险程度分层
        // drug 0 1
        boolean drug = this.getDrug(resultList, map);
        // disease_level 0 1 2 3
        int diseaseLevel = this.getLevel(resultList, map);

        // todo pydto.setResult("您的血压值在正常范围内，身体若有不适请到当地医院做详细检查以明确诊断！"); 100

        String riskLevel = this.getRiskLevel(resultList, diseaseLevel, map);
        // 2020/10/16 吴健人-》 去掉心血管分层
        riskLevel = "";
        // 症状
        List<String> disease = new ArrayList<>();
        String tt = "高血压" + (diseaseLevel > 0 ? (diseaseLevel + "级" + riskLevel) : "");
        disease.add(tt);
        if (map.containsKey(PatientConstant.QUESTION_SYMPTOM)) {
            map.get(PatientConstant.QUESTION_SYMPTOM).forEach(d -> {
                resultList.add(d);
                disease.add(d.getAnswer());
            });
        }
        if (map.containsKey(PatientConstant.QUESTION_DIAB)) {
            resultList.add(map.get(PatientConstant.QUESTION_DIAB).get(0));
            if (Constant.STRING_YES.equals(map.get(PatientConstant.QUESTION_DIAB).get(0).getAnswerTag())) {
                disease.add("糖尿病");
            }
        }
        // 存储疾病判断结果
        HphyGuideRecord update = new HphyGuideRecord();
        update.setId(guideId);
        update.setDisease(String.join(",", disease));
        update.setRiskLevel(riskLevel);
        this.updateById(update);

        return resultList;
    }

    @Override
    public List<DiseaseAnalysisDTO> analysisDiseaseV3(Long patientId, Long guideId) {
        List<DiseaseAnalysisDTO> dtoList = hphyGuideRecordMapper.listAnalysis(guideId);
        Map<String, List<DiseaseAnalysisDTO>> map = dtoList.stream().collect(Collectors.groupingBy(DiseaseAnalysisDTO::getQuestionTag));
        List<String> disease = new ArrayList<>();
        HphyGuideRecord update = new HphyGuideRecord();
        update.setId(guideId);
        // 是否确诊
        String isDefinite = "";
        if (map.containsKey(PatientConstant.QUESTION_DEFINITE)) {
            isDefinite = map.get(PatientConstant.QUESTION_DEFINITE).get(0).getAnswerTag();
            disease.add(isDefinite);
            update.setIsDefinite(isDefinite);
        }

        // 服药情况
        String drug = "";
        if (map.containsKey(PatientConstant.QUESTION_DRUG)) {
            drug = map.get(PatientConstant.QUESTION_DRUG).get(0).getAnswerTag();
            update.setDrugStatus(map.get(PatientConstant.QUESTION_DRUG).get(0).getAnswer());
        }
        // 妊娠期
        if (map.containsKey(PatientConstant.QUESTION_PREG)) {
            update.setIsGestation(map.get(PatientConstant.QUESTION_PREG).get(0).getAnswer());
            if (StrUtil.isNotBlank(map.get(PatientConstant.QUESTION_PREG).get(0).getAnswerTag())) {
                disease.add(map.get(PatientConstant.QUESTION_PREG).get(0).getAnswerTag());
            }
        }
        // 血压分级
        int level = 0;
        if (map.containsKey(PatientConstant.SBP)) {
            update.setSbp(map.get(PatientConstant.SBP).get(0).getAnswer());
            level = Integer.valueOf(map.get(PatientConstant.SBP).get(0).getAnswerTag());
        }
        if (map.containsKey(PatientConstant.DBP)) {
            update.setDbp(map.get(PatientConstant.DBP).get(0).getAnswer());
            int temp = Integer.valueOf(map.get(PatientConstant.DBP).get(0).getAnswerTag());
            if (temp > level) {
                level = temp;
            }
        }
        String levelDisease = this.getDiseaseLevel(level);
        disease.add(levelDisease);
        DiseaseAnalysisDTO dto = new DiseaseAnalysisDTO();
        dto.setQuestion("您的血压水平：");
        if (level > 0) {
            if (StrUtil.isNotBlank(drug)) {
                disease.add(drug);
            }
        }
        dto.setAnswer(levelDisease);
        dtoList.add(dto);
        if (map.containsKey(PatientConstant.QUESTION_SYMPTOM)) {
            List<String> symptom = new ArrayList<>();
            map.get(PatientConstant.QUESTION_SYMPTOM).forEach(qa -> {
                if (StrUtil.isNotBlank(qa.getAnswer())) {
                    disease.add(qa.getAnswer());
                    symptom.add(qa.getAnswer());
                }
            });
            update.setSymptom(String.join(StringPool.SEMICOLON, symptom));
        }
        update.setDisease(String.join(StringPool.SEMICOLON, disease));
        // 高血压等级
        update.setUpdateTime(DateUtil.date());
        this.updateById(update);
        return dtoList;
    }

    @Override
    public R getPythonResult(Long guideId) throws UnsupportedEncodingException {
        // 调用python程序分析
        HphyGuideRecord guide = this.getById(guideId);
        if (null == guide || NumberUtil.isNullOrZero(guide.getId())) {
            return new R().error("未找到导医记录!");
        }
        if (StrUtil.isBlank(guide.getPyResult())) {
            HphyGuideRecord update = new HphyGuideRecord();
            update.setId(guideId);
            HphyPatientBase patient = hphyPatientBaseService.getById(guide.getPatientId());
            PythonDTO pydto = new PythonDTO(patient, new ArrayList<>(Arrays.asList(guide.getDisease().split(StringPool.SEMICOLON))));
            String pyResutl = PythonUtil.getDcotorMatchListForHP(JSONUtil.toJsonStr(pydto));
            update.setPyResult(pyResutl);
            update.setAge(patient.getAge());
            guide.setPyResult(pyResutl);
            this.updateById(update);
        }
        if (JSONUtil.isJson(guide.getPyResult())) {
            JSONObject obj = JSONUtil.parseObj(guide.getPyResult());
            // indicator 0-字符串 1-json
            if (Constant.STRING_YES.equals(obj.getStr("indicator"))) {
                List<PythonResult> pythonList = JSON.parseArray(obj.getStr("data"), PythonResult.class);
                List<DoctorMatchVO> resultList = hphyDoctorService.getRecommendList(guide, pythonList);
                return new R(resultList).setBizCode(200);
            } else {
                return new R(obj.getStr("data")).setBizCode(100);
            }
        } else {
            return new R(guide.getPyResult()).setBizCode(100);
        }
    }

    @Override
    public List<DiseaseAnalysisDTO> listAnalysis(Long guideId) {
        return hphyGuideRecordMapper.listAnalysis(guideId);
    }


    @Override
    public HphyGuideRecord getByPatientId(String patientId) {
        LambdaQueryWrapper<HphyGuideRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(HphyGuideRecord::getPatientId, patientId)
                .last("limit 1");
        return this.getOne(wrapper);
    }

    /**
     * 心血管危险程度分层
     *
     * @param map
     * @return
     */
    private String getRiskLevel(List<DiseaseAnalysisDTO> resultList, Integer level, Map<String, List<DiseaseAnalysisDTO>> map) {
        String result = "";
        if (map.containsKey(PatientConstant.QUESTION_RISKLEVEL)) {
            if (StrUtil.isNotBlank(map.get(PatientConstant.QUESTION_RISKLEVEL).get(0).getAnswerTag())) {
                result = map.get(PatientConstant.QUESTION_RISKLEVEL).get(0).getAnswerTag();
            }
        }
        if (StrUtil.isBlank(result)) {
            //      危险因素
            int riskCount = 0;
            //      靶器官损害
            int targetOrganCount = 0;
            //      并发症
            int symptomCount = 0;
            //      糖尿病
            boolean db = false;
            if (map.containsKey(PatientConstant.QUESTION_RISKFACTOR)) {
                riskCount = map.get(PatientConstant.QUESTION_RISKFACTOR).size();
            }
            if (map.containsKey(PatientConstant.QUESTION_TARGETORGAN)) {
                targetOrganCount = map.get(PatientConstant.QUESTION_TARGETORGAN).size();
            }
            if (map.containsKey(PatientConstant.QUESTION_SYMPTOM)) {
                symptomCount = map.get(PatientConstant.QUESTION_SYMPTOM).size();
            }
            if (map.containsKey(PatientConstant.QUESTION_DIAB)) {
                db = Constant.STRING_YES.equals(map.get(PatientConstant.QUESTION_DIAB).get(0).getAnswerTag());
            }
            if (PatientConstant.DISEASE_1.equals(level)) {
                if (map.containsKey(PatientConstant.QUESTION_SYMPTOM)) {
                    result = PatientConstant.RISK_LEVEL_3;
                } else {
                    if (riskCount > 2 || db || targetOrganCount > 0) {
                        result = PatientConstant.RISK_LEVEL_2;
                    } else if (riskCount > 0) {
                        result = PatientConstant.RISK_LEVEL_1;
                    } else {
                        result = PatientConstant.RISK_LEVEL_0;
                    }
                }
            } else if (PatientConstant.DISEASE_2.equals(level)) {
                if (symptomCount > 0) {
                    result = PatientConstant.RISK_LEVEL_3;
                } else if (riskCount > 2 || db || targetOrganCount > 0) {
                    result = PatientConstant.RISK_LEVEL_2;
                } else {
                    result = PatientConstant.RISK_LEVEL_1;
                }
            } else if (PatientConstant.DISEASE_3.equals(level)) {
                if (riskCount > 0 || targetOrganCount > 0 || symptomCount > 0 || db) {
                    result = PatientConstant.RISK_LEVEL_3;
                } else {
                    result = PatientConstant.RISK_LEVEL_2;
                }
            }
        }
        if (CollUtil.isNotEmpty(resultList)) {
            DiseaseAnalysisDTO dto = new DiseaseAnalysisDTO();
            dto.setQuestion("您的心血管危险程度");
            dto.setAnswer(result);
            resultList.add(dto);
        }
        return result;
    }

    /**
     * 是否吃药
     * // diab 0 1
     *
     * @param map
     * @return
     */
    private boolean getDrug(List<DiseaseAnalysisDTO> resultList, Map<String, List<DiseaseAnalysisDTO>> map) {
        boolean result = false;
        if (map.containsKey(PatientConstant.QUESTION_DRUG)) {
            if (null != resultList) {
                resultList.add(map.get(PatientConstant.QUESTION_DRUG).get(0));
            }
            result = Constant.STRING_YES.equals(map.get(PatientConstant.QUESTION_DRUG).get(0).getAnswerTag());
        }
        return result;
    }


    /**
     * 计算高血压分层
     * // risk_level 低危 中危 高危 极高危
     * // risk_cal 计算心血管危险程度
     *
     * @param map
     * @return
     */
    private Integer getLevel(List<DiseaseAnalysisDTO> resultList, Map<String, List<DiseaseAnalysisDTO>> map) {
        AtomicInteger level = new AtomicInteger(0);
        // disease_cal  计算取较大值作为高血压分级
        if (map.containsKey(PatientConstant.QUESTION_DISEASELEVEL)) {
            if (StrUtil.isNotBlank(map.get(PatientConstant.QUESTION_DISEASELEVEL).get(0).getAnswerTag())) {
                level.set(Integer.valueOf(map.get(PatientConstant.QUESTION_DISEASELEVEL).get(0).getAnswerTag()));
            }
        }
        if (map.containsKey(PatientConstant.QUESTION_DISEASECAL)) {
            List<DiseaseAnalysisDTO> tempList = map.get(PatientConstant.QUESTION_DISEASECAL);
            tempList.forEach(t -> {
                if (Integer.valueOf(t.getAnswerTag()) > level.get()) {
                    level.set(Integer.valueOf(t.getAnswerTag()));
                }
            });
        }
        if (null != resultList) {
            DiseaseAnalysisDTO dto = new DiseaseAnalysisDTO();
            dto.setQuestion("您的血压水平");
            String tt = "无";
            if (level.get() > 0) {
                tt = "高血压" + level.get() + "级";
            }
            dto.setAnswer(tt);
            resultList.add(dto);
        }
        return level.get();
    }

    private String getDiseaseLevel(int level) {
        String result = "正常血压";
        switch (level) {
            case -1:
                result = "正常血压";
                break;
            case 0:
                result = "正常高值";
                break;
            default:
                result = "高血压" + level + "级";
                break;
        }
        return result;
    }
}
