package com.ningdatech.pmapi.dashboard.manage;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.pmapi.dashboard.constant.ChartTypeEnum;
import com.ningdatech.pmapi.dashboard.helper.DashboardChartAssembler;
import com.ningdatech.pmapi.dashboard.helper.DashboardHelper;
import com.ningdatech.pmapi.dashboard.model.basic.AnalysisChart;
import com.ningdatech.pmapi.dashboard.model.basic.AnalysisData;
import com.ningdatech.pmapi.dashboard.model.basic.StarExpertBO;
import com.ningdatech.pmapi.dashboard.model.po.QueryYearPO;
import com.ningdatech.pmapi.dashboard.model.vo.ExpertDashboardSummaryVO;
import com.ningdatech.pmapi.expert.constant.ExpertUserInfoStepEnum;
import com.ningdatech.pmapi.expert.entity.ExpertUserFullInfo;
import com.ningdatech.pmapi.expert.service.IExpertUserFullInfoService;
import com.ningdatech.pmapi.meeting.entity.domain.Meeting;
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpertJudge;
import com.ningdatech.pmapi.meeting.entity.enumeration.MeetingStatusEnum;
import com.ningdatech.pmapi.meeting.service.IMeetingExpertJudgeService;
import com.ningdatech.pmapi.meeting.service.IMeetingService;
import com.ningdatech.pmapi.meta.constant.DictExpertInfoTypeEnum;
import com.ningdatech.pmapi.meta.model.entity.ExpertDictionary;
import com.ningdatech.pmapi.meta.service.IExpertDictionaryService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author liuxinxin
 * @date 2023/8/2 上午10:39
 */

@Component
@RequiredArgsConstructor
public class DashboardExpertManage {

    private final DashboardHelper dashboardHelper;
    private final IExpertUserFullInfoService iExpertUserFullInfoService;
    private final IMeetingService iMeetingService;
    //    private final DictionaryCache dictionaryCache;
    private final IMeetingExpertJudgeService iMeetingExpertJudgeService;
    private final IExpertDictionaryService iExpertDictionaryService;
    private final DashboardChartAssembler dashboardChartAssembler;


    public ExpertDashboardSummaryVO getExpertDashboardSummary(QueryYearPO queryYearPO) {
        String queryRegionCode = queryYearPO.getRegionCode();
        List<AnalysisChart> analysisChartList = new ArrayList<>();

        // 获取丽水区域 code name Map
        Map<String, String> liShuiRegionCodeNameMap = dashboardHelper.getLiShuiRegionCodeNameMap();
        // 获取库内所有的专家列表
        List<ExpertUserFullInfo> evidenceHasBeenSubmittedExpertInfoList = iExpertUserFullInfoService.list(Wrappers.lambdaQuery(ExpertUserFullInfo.class)
                .eq(ExpertUserFullInfo::getUserInfoStep, ExpertUserInfoStepEnum.EVIDENCE_HAS_BEEN_SUBMITTED.getKey()));

        // 专家regionCode分组map列表
        Map<String, List<ExpertUserFullInfo>> regionCodeExpertMap = evidenceHasBeenSubmittedExpertInfoList.stream()
                .collect(Collectors.groupingBy(ExpertUserFullInfo::getRegionCode));

        // 各区域专家数量
        AnalysisChart regionExpertNumberChartAnalysisChart = new AnalysisChart();
        List<AnalysisData> regionExpertNumberChartDataList = new ArrayList<>();
        regionExpertNumberChartAnalysisChart.setChartType(ChartTypeEnum.REGION_EXPERT_NUMBER_CHART);
        regionExpertNumberChartAnalysisChart.setDataList(regionExpertNumberChartDataList);
        for (String regionCode : liShuiRegionCodeNameMap.keySet()) {
            AnalysisData analysisData = new AnalysisData();
            String regionName = liShuiRegionCodeNameMap.get(regionCode);
            List<ExpertUserFullInfo> expertUserFullInfoList = regionCodeExpertMap.get(regionCode);
            Integer expertCnt = 0;
            if (CollectionUtil.isNotEmpty(expertUserFullInfoList)) {
                expertCnt = expertUserFullInfoList.size();
            }
            analysisData.setKey(regionName);
            analysisData.setValue(expertCnt);
            regionExpertNumberChartDataList.add(analysisData);
        }
        analysisChartList.add(regionExpertNumberChartAnalysisChart);

        // 查询区域的专家id 列表
        List<Long> regionDegreeExpertIdList = new ArrayList<>();
        if (StringUtils.isNotBlank(queryRegionCode)) {
            List<ExpertUserFullInfo> expertUserFullInfoList = regionCodeExpertMap.get(queryRegionCode);
            if (CollectionUtil.isNotEmpty(expertUserFullInfoList)) {
                regionDegreeExpertIdList = expertUserFullInfoList.stream()
                        .map(ExpertUserFullInfo::getUserId)
                        .collect(Collectors.toList());
            }
        } else {
            regionDegreeExpertIdList = evidenceHasBeenSubmittedExpertInfoList.stream()
                    .map(ExpertUserFullInfo::getUserId)
                    .collect(Collectors.toList());
        }

        if (CollectionUtil.isNotEmpty(regionDegreeExpertIdList)) {
            // 区域学历分布
            List<ExpertDictionary> degreeExpertDictionaryList = iExpertDictionaryService
                    .listByUserId(regionDegreeExpertIdList, DictExpertInfoTypeEnum.DEGREE);
            Map<String, List<String>> degreeCodeMap = degreeExpertDictionaryList.stream()
                    .map(ExpertDictionary::getDictionaryCode)
                    .collect(Collectors.groupingBy(Function.identity()));
            AnalysisChart regionExpertEducationChartAnalysisChart =
                    dashboardChartAssembler.assemblerAnalysisChart(degreeCodeMap, ChartTypeEnum.REGION_EXPERT_EDUCATION_CHART);
            analysisChartList.add(regionExpertEducationChartAnalysisChart);

            // 区域职称级别分布
            List<ExpertDictionary> titleLevelExpertDictionaryList = iExpertDictionaryService
                    .listByUserId(regionDegreeExpertIdList, DictExpertInfoTypeEnum.TITLE_LEVEL);
            Map<String, List<ExpertDictionary>> titleLevelCodeMap = titleLevelExpertDictionaryList.stream()
                    .collect(Collectors.groupingBy(ExpertDictionary::getDictionaryCode));
            AnalysisChart regionExpertTitleLevelChartAnalysisChart =
                    dashboardChartAssembler.assemblerAnalysisChart(titleLevelCodeMap, ChartTypeEnum.REGION_EXPERT_TITLE_LEVEL_CHART);
            analysisChartList.add(regionExpertTitleLevelChartAnalysisChart);
        }

        // 评审次数
        List<Meeting> normalMeetingList = iMeetingService.list(Wrappers.lambdaQuery(Meeting.class)
                .eq(StringUtils.isNotBlank(queryRegionCode), Meeting::getRegionCode, queryRegionCode)
                .ne(Meeting::getStatus, MeetingStatusEnum.CANCELED.getCode()));
        Integer meetingCnt = normalMeetingList.size();

        // 各类型评审次数
        Map<String, List<Meeting>> meetingTypeMap = normalMeetingList.stream().collect(Collectors.groupingBy(Meeting::getType));
        AnalysisChart meetingTypeCntChartAnalysisChart =
                dashboardChartAssembler.assemblerAnalysisChart(meetingTypeMap, ChartTypeEnum.MEETING_TYPE_CNT_CHART);
        analysisChartList.add(meetingTypeCntChartAnalysisChart);

        // 明星专家列表
        List<StarExpertBO> starExpertList = new ArrayList<>();
        List<MeetingExpertJudge> meetingExpertJudgeList = iMeetingExpertJudgeService.list();
        Map<Long, List<MeetingExpertJudge>> expertIdMeetingExpertJudgeMap = meetingExpertJudgeList.stream()
                .collect(Collectors.groupingBy(MeetingExpertJudge::getExpertId));
        Map<Long, String> expertIdExpertNameMap = evidenceHasBeenSubmittedExpertInfoList.stream()
                .collect(Collectors.toMap(ExpertUserFullInfo::getUserId, ExpertUserFullInfo::getExpertName));

        for (Long expertId : expertIdMeetingExpertJudgeMap.keySet()) {
            String expertName = expertIdExpertNameMap.get(expertId);
            List<MeetingExpertJudge> expertMeetingExpertJudgeList = expertIdMeetingExpertJudgeMap.get(expertId);
            DoubleSummaryStatistics statistics = expertMeetingExpertJudgeList
                    .stream().filter(r -> Objects.nonNull(r.getScore()))
                    .map(MeetingExpertJudge::getScore).mapToDouble(Number::doubleValue).summaryStatistics();
            double average = statistics.getAverage();
            StarExpertBO starExpertBO = new StarExpertBO();
            starExpertBO.setAveragePerformanceScore(average);
            starExpertBO.setExpertId(expertId);
            starExpertBO.setExpertName(expertName);
            starExpertList.add(starExpertBO);
        }
        starExpertList = starExpertList.stream()
                .sorted(Comparator.comparing(StarExpertBO::getAveragePerformanceScore)
                        .reversed()).collect(Collectors.toList());
        if (starExpertList.size() > 5) {
            starExpertList = starExpertList.subList(0, 5);
        }

        // 装配返回类
        ExpertDashboardSummaryVO expertDashboardSummaryVO = new ExpertDashboardSummaryVO();
        expertDashboardSummaryVO.setMeetingCnt(meetingCnt);
        expertDashboardSummaryVO.setStarExpertList(starExpertList);
        expertDashboardSummaryVO.setAnalysisChartList(analysisChartList);
        return expertDashboardSummaryVO;
    }

}

