package com.supervision.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.supervision.exception.BusinessException;
import com.supervision.model.Process;
import com.supervision.model.*;
import com.supervision.pojo.vo.*;
import com.supervision.service.*;
import com.supervision.vo.ask.TreatmentPlanRecordVo;
import com.supervision.vo.manage.DiseaseTreatmentPlanResVo;
import com.supervision.vo.result.AncillaryRecordByResultDTO;
import com.supervision.vo.result.PhysicalRecordByResultDTO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class AskDiagnosisResultServiceImpl implements AskDiagnosisResultService {

    private final DiagnosisPrimaryService diagnosisPrimaryService;

    private final AskPatientAnswerService askPatientAnswerService;

    private final MedicalRecService medicalRecService;

    private final DiagnosisQaRecordService diagnosisQaRecordService;

    private final DiagnosisPhysicalRecordService diagnosisPhysicalRecordService;

    private final DiagnosisAncillaryRecordService diagnosisAncillaryRecordService;

    private final ProcessService processService;

    private final DiseaseService diseaseService;

    private final TreatmentPlanRecordService treatmentPlanRecordService;

    private final DiseaseTreatmentPlanService diseaseTreatmentPlanService;

    private final DiseaseTreatmentPlanDrugService diseaseTreatmentPlanDrugService;

    private final DiseasePhysicalService diseasePhysicalService;

    private final DiseaseAncillaryService diseaseAncillaryService;


    @Override
    public DiagnosisResultResVO queryDiagnosisResult(String processId) {
        DiagnosisResultResVO diagnosisResultResVO = new DiagnosisResultResVO();
        diagnosisResultResVO.setId(processId);
        Process process = processService.getById(processId);
        MedicalRec medicalRec = medicalRecService.getById(process.getMedicalRecId());
        List<Disease> diseasesList = diseaseService.listDiseaseNestIfComposite(medicalRec.getDiseaseId());
        // 1.生成预期诊断结果
        diagnosisResultResVO.setExpertDiagnosisResult(creatExpertDiagnosisResult(medicalRec, diseasesList, processId));
        // 2.生成初步诊断依据
        diagnosisResultResVO.setBasisPrimaryResultResVO(createBasisPrimaryResult(medicalRec, process));
        // 3.生成证实诊断依据
        diagnosisResultResVO.setBasisConfirmResultResVO(createBasisConfirmResult(medicalRec, processId));
        // 4.生成鉴别诊断依据
        diagnosisResultResVO.setBasisIdentificationResult(createBasisIdentificationResult(medicalRec, processId));
        // 5.全面检查-(暂无相关数据) 后面再看
        diagnosisResultResVO.setFullCheck(null);
        // 6.处置方案
        diagnosisResultResVO.setDealPlan(createDealPlan(process.getDiseaseId(), processId));
        return diagnosisResultResVO;
    }

    private DealPlanResVO createDealPlan(String diseaseId, String processId) {

        DealPlanResVO dealPlanResVO = new DealPlanResVO();

        // 1. 查询处置计划记录
        List<? extends TreatmentPlanRecord> treatmentPlanRecordList = treatmentPlanRecordService.queryByProcessId(processId);
        if (CollectionUtil.isEmpty(treatmentPlanRecordList)) {
            return dealPlanResVO;
        }

        // 2. 查询出疾病处置计划
        List<DiseaseTreatmentPlanResVo> diseaseTreatmentPlanResVos = diseaseTreatmentPlanService.queryListByDiseaseId(diseaseId);
        List<String> planIds = diseaseTreatmentPlanResVos.stream().map(DiseaseTreatmentPlanResVo::getPlanId).distinct().collect(Collectors.toList());

        // 3. 查出疾病处置计划用药
        List<DiseaseTreatmentPlanDrug> diseaseTreatmentPlanDrugList = diseaseTreatmentPlanDrugService.lambdaQuery().eq(DiseaseTreatmentPlanDrug::getDiseaseId, diseaseId).list();
        List<String> drugIds = diseaseTreatmentPlanDrugList.stream().map(DiseaseTreatmentPlanDrug::getDrugId).distinct().collect(Collectors.toList());

        // 4. 组装数据
        ArrayList<TreatmentPlanRecordVo> drugTreatmentPlanResults = new ArrayList<>();
        ArrayList<TreatmentPlanRecordVo> otherTreatmentPlanResults = new ArrayList<>();
        for (TreatmentPlanRecord treatmentPlanRecord : treatmentPlanRecordList) {
            TreatmentPlanRecordVo bean = BeanUtil.toBean(treatmentPlanRecord, TreatmentPlanRecordVo.class);
            boolean flag = StrUtil.isNotEmpty(bean.getDrugId()) ? drugIds.contains(bean.getDrugId()) : planIds.contains(bean.getTreatmentPlanId());
            bean.setFlag(flag ? 1 : 0);
            if (StrUtil.isNotEmpty(bean.getDrugId())) {
                drugTreatmentPlanResults.add(bean);
            } else {
                otherTreatmentPlanResults.add(bean);
            }

        }
        dealPlanResVO.setUserTreatmentPlanType(CollectionUtil.getFirst(treatmentPlanRecordList).getDisposalMethod());
        dealPlanResVO.setDrugTreatmentPlan(drugTreatmentPlanResults);
        dealPlanResVO.setOtherTreatmentPlan(otherTreatmentPlanResults.stream().sorted(
                Comparator.comparing(TreatmentPlanRecord::getDisposalPlan)).collect(Collectors.toList()));
        return dealPlanResVO;

    }

    private BasisIdentificationResultResVO createBasisIdentificationResult(MedicalRec medicalRec, String processId) {
        BasisIdentificationResultResVO basisIdentificationResultResVO = new BasisIdentificationResultResVO();
        // 鉴别诊断依据,来自于medicalRec的DifferentialDiagnosisCriteria
        basisIdentificationResultResVO.setIdentificationDiagnosis(medicalRec.getDifferentialDiagnosisCriteria());
        // 2.2 获取体格检查
        List<PhysicalRecordByResultDTO> physicalRecordList = diagnosisPhysicalRecordService.queryPhysicalResultByProcessId(processId);
        List<BasisDiagnosisNodeResVO> nodeList = physicalRecordList.stream()
                .filter(distinctPredicateNotNull(PhysicalRecordByResultDTO::getToolLocationName)).map(e -> {
                    BasisDiagnosisNodeResVO nodeResVO = new BasisDiagnosisNodeResVO();
                    nodeResVO.setType(1);
                    nodeResVO.setRecordName(e.getToolLocationName());
                    nodeResVO.setRecordId(e.getRecordId());
                    nodeResVO.setCorrect(
                            (ObjectUtil.isNotNull(e.getBasisConfirm()) && 1 == e.getBasisIdentification() && Objects.equals(e.getBasisIdentification(), e.getRecordBasisIdentificationFlag()))
                                    ? 1 : 0);
                    return nodeResVO;
                }).collect(Collectors.toList());
        // 2.3 获取辅助检查
        List<AncillaryRecordByResultDTO> ancillaryRecordList = diagnosisAncillaryRecordService.queryAncillaryResultByProcessId(processId);
        List<BasisDiagnosisNodeResVO> collect = ancillaryRecordList.stream()
                .filter(distinctPredicateNotNull(AncillaryRecordByResultDTO::getItemName)).map(e -> {
                    BasisDiagnosisNodeResVO nodeResVO = new BasisDiagnosisNodeResVO();
                    nodeResVO.setCorrect(
                            (ObjectUtil.isNotNull(e.getBasisConfirm()) && 1 == e.getBasisIdentification() && Objects.equals(e.getBasisIdentification(), e.getRecordBasisIdentificationFlag()))
                                    ? 1 : 0);
                    nodeResVO.setRecordId(e.getRecordId());
                    nodeResVO.setRecordName(e.getItemName());
                    nodeResVO.setType(2);
                    return nodeResVO;
                }).collect(Collectors.toList());
        nodeList.addAll(collect);

        basisIdentificationResultResVO.setNodeList(nodeList);
        return basisIdentificationResultResVO;
    }

    private BasisConfirmResultResVO createBasisConfirmResult(MedicalRec medicalRec, String processId) {
        BasisConfirmResultResVO basisConfirmResultResVO = new BasisConfirmResultResVO();
        // 证实诊断依据,来自于medicalRec的ConfirmDiagnosisCriteria
        basisConfirmResultResVO.setConfirmingDiagnosis(medicalRec.getConfirmDiagnosisCriteria());
        // 2.2 获取体格检查的证实诊断依据
        List<PhysicalRecordByResultDTO> physicalRecordList = diagnosisPhysicalRecordService.queryPhysicalResultByProcessId(processId);
        List<BasisDiagnosisNodeResVO> nodeList = physicalRecordList.stream()
                .filter(distinctPredicateNotNull(PhysicalRecordByResultDTO::getToolLocationName)).map(e -> {
                    BasisDiagnosisNodeResVO nodeResVO = new BasisDiagnosisNodeResVO();
                    nodeResVO.setType(1);
                    nodeResVO.setRecordName(e.getToolLocationName());
                    nodeResVO.setRecordId(e.getRecordId());
                    nodeResVO.setCorrect(
                            (ObjectUtil.isNotNull(e.getBasisConfirm()) && 1 == e.getBasisConfirm() && Objects.equals(e.getBasisConfirm(), e.getRecordBasisConfirmFlag()))
                                    ? 1 : 0);
                    return nodeResVO;
                }).collect(Collectors.toList());

        // 2.3 获取辅助检查
        List<AncillaryRecordByResultDTO> ancillaryRecordList = diagnosisAncillaryRecordService.queryAncillaryResultByProcessId(processId);
        List<BasisDiagnosisNodeResVO> collect = ancillaryRecordList.stream()
                .filter(distinctPredicateNotNull(AncillaryRecordByResultDTO::getItemName)).map(e -> {
                    BasisDiagnosisNodeResVO nodeResVO = new BasisDiagnosisNodeResVO();
                    nodeResVO.setCorrect(
                            (ObjectUtil.isNotNull(e.getBasisConfirm()) && 1 == e.getBasisConfirm() && Objects.equals(e.getBasisConfirm(), e.getRecordBasisConfirmFlag()))
                                    ? 1 : 0);
                    nodeResVO.setRecordId(e.getRecordId());
                    nodeResVO.setRecordName(e.getItemName());
                    nodeResVO.setType(2);
                    return nodeResVO;
                }).collect(Collectors.toList());
        nodeList.addAll(collect);

        basisConfirmResultResVO.setNodeList(nodeList);
        return basisConfirmResultResVO;
    }

    private BasisPrimaryResultResVO createBasisPrimaryResult(MedicalRec medicalRec, Process process) {
        BasisPrimaryResultResVO basisPrimaryResultResVO = new BasisPrimaryResultResVO();
        // 初步诊断依据 vp_medical_rec的primarily_diagnosis_criteria
        basisPrimaryResultResVO.setPreliminaryDiagnosis(medicalRec.getPrimarilyDiagnosisCriteria());
        // 根据record记录寻找符合初步诊断依据的项目
        // 2.1 首先获取对话
        List<BasisDiagnosisNodeResVO> basisDiagnosisNodeResVOS = new ArrayList<>();
        List<DiagnosisQaRecord> qaRecordList = diagnosisQaRecordService.lambdaQuery().eq(DiagnosisQaRecord::getProcessId, process.getId()).list();
        if (CollectionUtil.isNotEmpty(qaRecordList)) {
            List<AskPatientAnswer> list = askPatientAnswerService.lambdaQuery()
                    .eq(AskPatientAnswer::getMedicalId, medicalRec.getId()).list();
            // 获取配置了答案的项目(配置了答案的,认为是正确,没有配置答案的,走默认回答的,不标记为以正确)
            Set<String> requireCheckIdSet = list.stream().map(AskPatientAnswer::getId).collect(Collectors.toSet());
            List<BasisDiagnosisNodeResVO> qaList = qaRecordList.stream().map(e -> {
                BasisDiagnosisNodeResVO node = new BasisDiagnosisNodeResVO();
                node.setType(0);
                node.setRecordName(e.getQuestion());
                node.setRecordId(e.getId());
                node.setCorrect(requireCheckIdSet.contains(e.getAnswerId()) ? 1 : 0);
                return node;

            }).collect(Collectors.toList());
            basisDiagnosisNodeResVOS.addAll(qaList);
        }
        // 2.2 获取体格检查
        List<PhysicalRecordByResultDTO> physicalRecordList = diagnosisPhysicalRecordService.queryPhysicalResultByProcessId(process.getId());
        List<BasisDiagnosisNodeResVO> physicalList = physicalRecordList.stream()
                .filter(distinctPredicateNotNull(PhysicalRecordByResultDTO::getToolLocationName)).map(e -> {
                    BasisDiagnosisNodeResVO nodeResVO = new BasisDiagnosisNodeResVO();
                    nodeResVO.setType(1);
                    nodeResVO.setRecordName(e.getToolLocationName());
                    nodeResVO.setRecordId(e.getRecordId());
                    // 如果是初步诊断依据
                    nodeResVO.setCorrect(e.getPrimarilyDiagnosisCriteriaFlag());
                    return nodeResVO;
                }).collect(Collectors.toList());
        basisDiagnosisNodeResVOS.addAll(physicalList);
        // 2.3 获取辅助检查
        List<AncillaryRecordByResultDTO> ancillaryRecordList = diagnosisAncillaryRecordService.queryAncillaryResultByProcessId(process.getId());
        List<BasisDiagnosisNodeResVO> collect = ancillaryRecordList.stream()
                .filter(distinctPredicateNotNull(AncillaryRecordByResultDTO::getItemName)).map(e -> {
                    BasisDiagnosisNodeResVO nodeResVO = new BasisDiagnosisNodeResVO();

                    nodeResVO.setCorrect(e.getPrimarilyDiagnosisCriteriaFlag());
                    nodeResVO.setRecordId(e.getRecordId());
                    nodeResVO.setRecordName(e.getItemName());
                    nodeResVO.setType(2);
                    return nodeResVO;
                }).collect(Collectors.toList());
        basisDiagnosisNodeResVOS.addAll(collect);

        basisPrimaryResultResVO.setNodeList(basisDiagnosisNodeResVOS);
        return basisPrimaryResultResVO;
    }


    /**
     * 预期诊断结果
     */
    private ExpertDiagnosisResultResVO creatExpertDiagnosisResult(MedicalRec medicalRec, List<Disease> diseasesList, String processId) {
        ExpertDiagnosisResultResVO expertDiagnosisResultResVO = new ExpertDiagnosisResultResVO();
        expertDiagnosisResultResVO.setDiagnosis(diseasesList.stream().map(Disease::getDiseaseNameAlias).collect(Collectors.joining(";")));
        Set<String> expertDiseaseIdSet = diseasesList.stream().map(Disease::getId).collect(Collectors.toSet());
        // 从vp_diagnosis_primary中找到确认诊断时,确认的
        List<DiagnosisPrimary> userPrimaryDiseaseList = diagnosisPrimaryService.lambdaQuery()
                .eq(DiagnosisPrimary::getProcessId, processId)
                // 1确诊
                .eq(DiagnosisPrimary::getExcludeFlag, 1).list();

        List<Disease> userDiagnosisDiseaseList = CollUtil.isEmpty(userPrimaryDiseaseList) ? CollUtil.newArrayList()
                : diseaseService.listByIds(userPrimaryDiseaseList.stream().map(DiagnosisPrimary::getPrimaryDiagnosisId).collect(Collectors.toList()));
        // 用户的诊断
        expertDiagnosisResultResVO.setUserDiagnosisResult(userDiagnosisDiseaseList.stream().map(e -> {
            DiagnosisDiseaseResultNodeVO userNode = new DiagnosisDiseaseResultNodeVO();
            userNode.setDiseaseName(e.getDiseaseNameAlias());
            // 如果用户诊断在预期诊断里面,则正确,否则错误
            userNode.setCorrect(expertDiseaseIdSet.contains(e.getId()) ? 1 : 0);
            userNode.setDiseaseId(e.getId());
            return userNode;
        }).collect(Collectors.toList()));

        // 预期诊断
        expertDiagnosisResultResVO.setExpertDiagnosisResult(diseasesList.stream().map(e -> {
            DiagnosisDiseaseResultNodeVO node = new DiagnosisDiseaseResultNodeVO();
            node.setDiseaseName(e.getDiseaseNameAlias());
            node.setDiseaseId(e.getId());
            return node;
        }).collect(Collectors.toList()));
        return expertDiagnosisResultResVO;
    }


    public static <K> Predicate<K> distinctPredicateNotNull(Function<K, Object> function) {
        ConcurrentHashMap<Object, Boolean> map = new ConcurrentHashMap<>();
        // 根据key进行去重,并排除为null的数据
        return t -> null != function.apply(t) && null == map.putIfAbsent(function.apply(t), true);

    }

    /**
     * 生成雷达图
     * <p>
     * ( 用户命中病历配置问题数 / 病历问题总数 ) * (用户提问命中病历配置问题数 / 用户实际提问的数量 )
     * <p>
     * Q:是否要区分是否是正常的检查结果?
     * A:雷达图 不管正常异常检查结果  只看该不该检查这个项目
     * Q:该不该,指的是病历的配置项是吗?只要配置了,就是该检查的
     * A:是的
     *
     * @param processId
     */
    @Override
    public RadarChartResVO queryRadarChart(String processId) {
        Process process = Optional.ofNullable(processService.getById(processId)).orElseThrow(() -> new BusinessException("未找到流程"));
        // 生成问诊雷达图
        BigDecimal askChart = computeAskChart(process);
        // 生成体格检查雷达图
        BigDecimal physicalChart = computePhysicalChart(process);
        // 生成辅助检查雷达图
        BigDecimal ancillaryChart = computeAncillaryChart(process);
        // 生成处置计划雷达图
        BigDecimal treatmentPlanChart = computeTreatmentPlanChart(process);
        RadarChartResVO radarChartResVO = new RadarChartResVO();
        radarChartResVO.setAskChart(askChart);
        radarChartResVO.setPhysicalChart(physicalChart);
        radarChartResVO.setAncillaryChart(ancillaryChart);
        radarChartResVO.setTreatmentPlanChart(treatmentPlanChart);
        BigDecimal clinicalThinking = NumberUtil.add(askChart, physicalChart, ancillaryChart, treatmentPlanChart).divide(BigDecimal.valueOf(4), 1, RoundingMode.HALF_UP);
        radarChartResVO.setClinicalThinking(clinicalThinking);
        return radarChartResVO;


    }

    /**
     * 生成处置计划雷达图
     * ( 用户命中病历治疗计划配置问题数 / 疾病配置的治疗计划总数 ) * (用户命中病历治疗计划配置问题数 / 用户实际填写的治疗计划的数量 )
     */
    private BigDecimal computeTreatmentPlanChart(Process process) {
        // 查询用户填写的治疗计划
        List<TreatmentPlanRecord> userTreatmentPlanRecordList = treatmentPlanRecordService.lambdaQuery().eq(TreatmentPlanRecord::getProcessId, process.getId()).list();
        int userTreatmentPlanCount = userTreatmentPlanRecordList.size();
        // 查询疾病配置的治疗计划
        List<DiseaseTreatmentPlan> planList = diseaseTreatmentPlanService.lambdaQuery().eq(DiseaseTreatmentPlan::getDiseaseId, process.getDiseaseId()).select(DiseaseTreatmentPlan::getId).list();
        List<String> planIdList = planList.stream().map(DiseaseTreatmentPlan::getId).collect(Collectors.toList());
        // 疾病配置的治疗计划总数
        int medicalCount = planIdList.size();
        // 找到用户配置的药物计划
        List<DiseaseTreatmentPlanDrug> drugList = diseaseTreatmentPlanDrugService.lambdaQuery().eq(DiseaseTreatmentPlanDrug::getDiseaseId, process.getDiseaseId()).select(DiseaseTreatmentPlanDrug::getDrugId).list();
        List<String> drugIdList = drugList.stream().map(DiseaseTreatmentPlanDrug::getDrugId).collect(Collectors.toList());
        int hitPlanCount = 0;
        for (TreatmentPlanRecord treatmentPlanRecord : userTreatmentPlanRecordList) {
            // 需要分别看是否是药物计划
            if (StrUtil.isNotBlank(treatmentPlanRecord.getTreatmentPlanId()) && planIdList.contains(treatmentPlanRecord.getTreatmentPlanId())) {
                hitPlanCount++;
            }
            if (StrUtil.isNotBlank(treatmentPlanRecord.getDrugId()) && drugIdList.contains(treatmentPlanRecord.getDrugId())) {
                hitPlanCount++;
            }
        }
        // 过程数据3:问诊vs问诊正确率
        BigDecimal num3 = BigDecimal.ZERO;
        if (userTreatmentPlanCount > 0) {
            num3 = BigDecimal.valueOf(hitPlanCount).divide(BigDecimal.valueOf(userTreatmentPlanCount), 1, RoundingMode.HALF_UP);
        }
        // 过程数据2:问诊vs标准正确率
        BigDecimal num2 = BigDecimal.ZERO;
        if (medicalCount > 0) {
            num2 = BigDecimal.valueOf(hitPlanCount).divide(BigDecimal.valueOf(medicalCount), 1, RoundingMode.HALF_UP);
        }
        return num2.multiply(num3);

    }

    /**
     * 生成辅助检查雷达图
     * ( 用户命中病历配置问题数 / 病历问题总数 ) * (用户提问命中病历配置问题数 / 用户实际提问的数量 )
     */
    private BigDecimal computeAncillaryChart(Process process) {
        Integer userHitCount = diagnosisAncillaryRecordService.lambdaQuery().isNotNull(DiagnosisAncillaryRecord::getAncillaryId)
                .eq(DiagnosisAncillaryRecord::getProcessId, process.getId()).count();
        Integer userCount = diagnosisAncillaryRecordService.lambdaQuery().eq(DiagnosisAncillaryRecord::getProcessId, process.getId()).count();
        Integer medicalCount = diseaseAncillaryService.lambdaQuery().eq(DiseaseAncillary::getDiseaseId, process.getDiseaseId()).count();
        // 过程数据3:问诊vs问诊正确率
        BigDecimal num3 = BigDecimal.ZERO;
        if (userCount > 0) {
            num3 = BigDecimal.valueOf(userHitCount).divide(BigDecimal.valueOf(userCount), 1, RoundingMode.HALF_UP);
        }
        // 过程数据2:问诊vs标准正确率
        BigDecimal num2 = BigDecimal.ZERO;
        if (medicalCount > 0) {
            num2 = BigDecimal.valueOf(userHitCount).divide(BigDecimal.valueOf(medicalCount), 1, RoundingMode.HALF_UP);
        }
        return num2.multiply(num3);
    }

    /**
     * 计算体格检查雷达图
     * 2. 体格检查:( 用户命中病历配置问题数 / 病历问题总数 ) * (用户提问命中病历配置问题数 / 用户实际提问的数量 )
     */
    private BigDecimal computePhysicalChart(Process process) {
        // 查询用户命中病历配置问题数
        Integer userHitCount = diagnosisPhysicalRecordService.lambdaQuery().isNotNull(DiagnosisPhysicalRecord::getPhysicalId)
                .eq(DiagnosisPhysicalRecord::getProcessId, process.getId()).count();
        // 查询用户实际检查数量
        Integer userCount = diagnosisPhysicalRecordService.lambdaQuery().eq(DiagnosisPhysicalRecord::getProcessId, process.getId()).count();
        // 查询病例配置的数量
        Integer medicalCount = diseasePhysicalService.lambdaQuery().eq(DiseasePhysical::getDiseaseId, process.getDiseaseId()).count();
        // 过程数据3:问诊vs问诊正确率
        BigDecimal num3 = BigDecimal.ZERO;
        if (userCount > 0) {
            num3 = BigDecimal.valueOf(userHitCount).divide(BigDecimal.valueOf(userCount), 1, RoundingMode.HALF_UP);
        }
        // 过程数据2:问诊vs标准正确率
        BigDecimal num2 = BigDecimal.ZERO;
        if (medicalCount > 0) {
            num2 = BigDecimal.valueOf(userHitCount).divide(BigDecimal.valueOf(medicalCount), 1, RoundingMode.HALF_UP);
        }
        return num2.multiply(num3);
    }


    /**
     * 生成问诊雷达图数据
     * 1. 问诊: ( 用户提问命中病历配置问题数 / 病历问题总数 ) * (用户提问命中病历配置问题数 / 用户实际提问的数量 )
     * 问诊vs标准正确率 * 问诊vs问诊正确率 = 综合正确率
     * 上面的数量都是去重的,未识别出来的问题,不包含在用户提问的数据里面
     * 默认语句不参与统计
     */
    public BigDecimal computeAskChart(Process process) {
        // 首先查询用户提问的病历问题(这里questionId不为null,即为识别出来的用户问题)
        List<DiagnosisQaRecord> qaRecordList = diagnosisQaRecordService.lambdaQuery().isNotNull(DiagnosisQaRecord::getQuestionLibraryId)
                .eq(DiagnosisQaRecord::getProcessId, process.getId()).list();
        // 用户实际提问数量(包含默认问题)
        Set<String> userQuestionIdSet = qaRecordList.stream().map(DiagnosisQaRecord::getQuestionLibraryId).collect(Collectors.toSet());
        // 查询病例配置的问题
        List<AskPatientAnswer> answerList = askPatientAnswerService.lambdaQuery().eq(AskPatientAnswer::getMedicalId, process.getMedicalRecId()).list();
        // 病历问题总数(统计非默认语句的病历问题总数)
        long medicalQuestionCount = answerList.stream().filter(e -> ObjectUtil.isNotEmpty(e.getAnswerType()) && 1 == e.getAnswerType()).count();
        // 用户实际提问的数量(去除默认问题)
        Set<String> defaultqQuestionIdSet = answerList.stream().filter(e -> ObjectUtil.isNotEmpty(e.getAnswerType()) && 0 == e.getAnswerType()).map(AskPatientAnswer::getLibraryQuestionId).collect(Collectors.toSet());
        userQuestionIdSet.removeAll(defaultqQuestionIdSet);
        int userQuestionCount = userQuestionIdSet.size();
        // 用户提问命中病历配置问题数(去除默认问题之后的交集)
        Collection<String> intersection = CollUtil.intersection(defaultqQuestionIdSet, answerList.stream().map(AskPatientAnswer::getLibraryQuestionId).collect(Collectors.toSet()));
        int userHitQuestionCount = intersection.size();

        // 过程数据3:问诊vs问诊正确率
        BigDecimal num3 = BigDecimal.ZERO;
        if (userQuestionCount > 0) {
            num3 = BigDecimal.valueOf(userHitQuestionCount).divide(BigDecimal.valueOf(userQuestionCount), 1, RoundingMode.HALF_UP);
        }
        // 过程数据2:问诊vs标准正确率
        BigDecimal num2 = BigDecimal.ZERO;
        if (medicalQuestionCount > 0) {
            num2 = BigDecimal.valueOf(userHitQuestionCount).divide(BigDecimal.valueOf(medicalQuestionCount), 1, RoundingMode.HALF_UP);
        }

        return num2.multiply(num3);
    }
}