package com.competition.modules.biz.review.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.competition.modules.biz.contest.entity.BizContest;
import com.competition.modules.biz.contest.entity.BizContestRegistration;
import com.competition.modules.biz.contest.entity.BizContestWork;
import com.competition.modules.biz.contest.mapper.ContestMapper;
import com.competition.modules.biz.contest.mapper.ContestRegistrationMapper;
import com.competition.modules.biz.contest.mapper.ContestWorkMapper;
import com.competition.modules.biz.review.entity.BizContestJudge;
import com.competition.modules.biz.review.entity.BizContestWorkJudgeAssignment;
import com.competition.modules.biz.review.entity.BizContestWorkScore;
import com.competition.modules.biz.review.mapper.ContestJudgeMapper;
import com.competition.modules.biz.review.mapper.ContestWorkJudgeAssignmentMapper;
import com.competition.modules.biz.review.mapper.ContestWorkScoreMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

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

@Service
@RequiredArgsConstructor
public class AnalyticsService {

    private final ContestMapper contestMapper;
    private final ContestRegistrationMapper contestRegistrationMapper;
    private final ContestWorkMapper contestWorkMapper;
    private final ContestWorkScoreMapper contestWorkScoreMapper;
    private final ContestWorkJudgeAssignmentMapper contestWorkJudgeAssignmentMapper;
    private final ContestJudgeMapper contestJudgeMapper;

    /**
     * 数据概览
     */
    public Map<String, Object> getOverview(Long tenantId, Long contestId) {
        Map<String, Object> result = new HashMap<>();

        // --- summary ---
        long totalContests = contestMapper.selectCount(
                new LambdaQueryWrapper<BizContest>()
                        .eq(tenantId != null, BizContest::getContestState, "published"));

        long totalRegistrations = contestRegistrationMapper.selectCount(
                new LambdaQueryWrapper<BizContestRegistration>()
                        .eq(contestId != null, BizContestRegistration::getContestId, contestId));

        long passedRegistrations = contestRegistrationMapper.selectCount(
                new LambdaQueryWrapper<BizContestRegistration>()
                        .eq(contestId != null, BizContestRegistration::getContestId, contestId)
                        .eq(BizContestRegistration::getRegistrationState, "passed"));

        long totalWorks = contestWorkMapper.selectCount(
                new LambdaQueryWrapper<BizContestWork>()
                        .eq(contestId != null, BizContestWork::getContestId, contestId)
                        .eq(BizContestWork::getIsLatest, true));

        long reviewedWorks = contestWorkScoreMapper.selectCount(
                new LambdaQueryWrapper<BizContestWorkScore>()
                        .eq(contestId != null, BizContestWorkScore::getContestId, contestId));

        long awardedWorks = contestWorkMapper.selectCount(
                new LambdaQueryWrapper<BizContestWork>()
                        .eq(contestId != null, BizContestWork::getContestId, contestId)
                        .eq(BizContestWork::getIsLatest, true)
                        .isNotNull(BizContestWork::getAwardLevel)
                        .ne(BizContestWork::getAwardLevel, "none"));

        Map<String, Object> summary = new LinkedHashMap<>();
        summary.put("totalContests", totalContests);
        summary.put("totalRegistrations", totalRegistrations);
        summary.put("passedRegistrations", passedRegistrations);
        summary.put("totalWorks", totalWorks);
        summary.put("reviewedWorks", reviewedWorks);
        summary.put("awardedWorks", awardedWorks);
        result.put("summary", summary);

        // --- funnel ---
        List<Map<String, Object>> funnel = new ArrayList<>();
        funnel.add(Map.of("stage", "报名", "count", totalRegistrations));
        funnel.add(Map.of("stage", "审核通过", "count", passedRegistrations));
        funnel.add(Map.of("stage", "提交作品", "count", totalWorks));
        funnel.add(Map.of("stage", "已评审", "count", reviewedWorks));
        funnel.add(Map.of("stage", "获奖", "count", awardedWorks));
        result.put("funnel", funnel);

        return result;
    }

    /**
     * 评审分析
     */
    public Map<String, Object> getReviewAnalysis(Long tenantId, Long contestId) {
        Map<String, Object> result = new HashMap<>();

        // --- efficiency ---
        long totalAssignments = contestWorkJudgeAssignmentMapper.selectCount(
                new LambdaQueryWrapper<BizContestWorkJudgeAssignment>()
                        .eq(contestId != null, BizContestWorkJudgeAssignment::getContestId, contestId));

        long completedAssignments = contestWorkJudgeAssignmentMapper.selectCount(
                new LambdaQueryWrapper<BizContestWorkJudgeAssignment>()
                        .eq(contestId != null, BizContestWorkJudgeAssignment::getContestId, contestId)
                        .eq(BizContestWorkJudgeAssignment::getStatus, "completed"));

        long totalScores = contestWorkScoreMapper.selectCount(
                new LambdaQueryWrapper<BizContestWorkScore>()
                        .eq(contestId != null, BizContestWorkScore::getContestId, contestId));

        Map<String, Object> efficiency = new LinkedHashMap<>();
        efficiency.put("totalAssignments", totalAssignments);
        efficiency.put("completedAssignments", completedAssignments);
        efficiency.put("completionRate", totalAssignments > 0
                ? Math.round(completedAssignments * 10000.0 / totalAssignments) / 100.0
                : 0);
        efficiency.put("totalScores", totalScores);
        result.put("efficiency", efficiency);

        // --- judgeWorkload ---
        List<BizContestJudge> judges = contestJudgeMapper.selectList(
                new LambdaQueryWrapper<BizContestJudge>()
                        .eq(contestId != null, BizContestJudge::getContestId, contestId));

        List<Map<String, Object>> judgeWorkload = judges.stream().map(judge -> {
            long assigned = contestWorkJudgeAssignmentMapper.selectCount(
                    new LambdaQueryWrapper<BizContestWorkJudgeAssignment>()
                            .eq(BizContestWorkJudgeAssignment::getJudgeId, judge.getJudgeId())
                            .eq(contestId != null, BizContestWorkJudgeAssignment::getContestId, contestId));
            long completed = contestWorkJudgeAssignmentMapper.selectCount(
                    new LambdaQueryWrapper<BizContestWorkJudgeAssignment>()
                            .eq(BizContestWorkJudgeAssignment::getJudgeId, judge.getJudgeId())
                            .eq(contestId != null, BizContestWorkJudgeAssignment::getContestId, contestId)
                            .eq(BizContestWorkJudgeAssignment::getStatus, "completed"));
            Map<String, Object> item = new LinkedHashMap<>();
            item.put("judgeId", judge.getJudgeId());
            item.put("specialty", judge.getSpecialty());
            item.put("assigned", assigned);
            item.put("completed", completed);
            item.put("completionRate", assigned > 0
                    ? Math.round(completed * 10000.0 / assigned) / 100.0
                    : 0);
            return item;
        }).collect(Collectors.toList());
        result.put("judgeWorkload", judgeWorkload);

        // --- awardDistribution ---
        long totalWorks = contestWorkMapper.selectCount(
                new LambdaQueryWrapper<BizContestWork>()
                        .eq(contestId != null, BizContestWork::getContestId, contestId)
                        .eq(BizContestWork::getIsLatest, true));

        List<String> awardLevels = List.of("first", "second", "third", "excellent");
        List<Map<String, Object>> awardDistribution = awardLevels.stream().map(level -> {
            long count = contestWorkMapper.selectCount(
                    new LambdaQueryWrapper<BizContestWork>()
                            .eq(contestId != null, BizContestWork::getContestId, contestId)
                            .eq(BizContestWork::getIsLatest, true)
                            .eq(BizContestWork::getAwardLevel, level));
            Map<String, Object> item = new LinkedHashMap<>();
            item.put("level", level);
            item.put("count", count);
            item.put("ratio", totalWorks > 0
                    ? Math.round(count * 10000.0 / totalWorks) / 100.0
                    : 0);
            return item;
        }).collect(Collectors.toList());
        result.put("awardDistribution", awardDistribution);

        return result;
    }
}
