package com.lesingle.creation.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lesingle.creation.common.enums.ContestStateEnum;
import com.lesingle.creation.dto.review.*;
import com.lesingle.creation.entity.*;
import com.lesingle.creation.common.exception.BusinessException;
import com.lesingle.creation.mapper.*;
import com.lesingle.creation.service.ContestReviewService;
import com.lesingle.creation.vo.review.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 竞赛评审服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ContestReviewServiceImpl implements ContestReviewService {

    private final ContestWorkAssignmentMapper assignmentMapper;
    private final ContestWorkMapper workMapper;
    private final ContestMapper contestMapper;
    private final ContestJudgeMapper judgeMapper;
    private final ContestWorkScoreMapper scoreMapper;
    private final UserMapper userMapper;
    private final ContestRegistrationMapper registrationMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ReviewAssignmentVO> assignWork(Long contestId, AssignWorkDTO dto, Long creatorId) {
        // 验证作品是否存在
        ContestWork work = workMapper.selectById(dto.getWorkId());
        if (work == null) {
            throw new BusinessException("作品不存在");
        }

        if (!work.getContestId().equals(contestId)) {
            throw new BusinessException("作品不属于该活动");
        }

        // 检查评审时间
        Contest contest = contestMapper.selectById(contestId);
        if (contest == null) {
            throw new BusinessException("活动不存在");
        }

        LocalDateTime now = LocalDateTime.now();
        if (now.isBefore(contest.getReviewStartTime()) || now.isAfter(contest.getReviewEndTime())) {
            throw new BusinessException("不在评审时间范围内");
        }

        // 验证评委是否存在且是该活动的评委
        List<ContestJudge> judges = judgeMapper.selectList(new LambdaQueryWrapper<ContestJudge>()
                .eq(ContestJudge::getContestId, contestId)
                .in(ContestJudge::getJudgeId, dto.getJudgeIds())
                .eq(ContestJudge::getValidState, 1)
                .eq(ContestJudge::getDeleted, 0));

        if (judges.size() != dto.getJudgeIds().size()) {
            throw new BusinessException("部分评委不存在或不是该活动的评委");
        }

        // 创建分配记录
        List<ReviewAssignmentVO> assignments = new ArrayList<>();
        for (Long judgeId : dto.getJudgeIds()) {
            // 检查是否已分配
            ContestWorkAssignment existing = assignmentMapper.selectOne(new LambdaQueryWrapper<ContestWorkAssignment>()
                    .eq(ContestWorkAssignment::getWorkId, dto.getWorkId())
                    .eq(ContestWorkAssignment::getJudgeId, judgeId)
                    .eq(ContestWorkAssignment::getDeleted, 0));

            if (existing != null) {
                continue; // 跳过已分配的
            }

            ContestWorkAssignment assignment = new ContestWorkAssignment();
            assignment.setContestId(contestId);
            assignment.setWorkId(dto.getWorkId());
            assignment.setJudgeId(judgeId);
            assignment.setStatus("assigned");
            assignment.setAssignTime(LocalDateTime.now());
            if (creatorId != null) {
                assignment.setCreateBy(creatorId.toString());
            }

            assignmentMapper.insert(assignment);
            assignments.add(convertToVO(assignment));
        }

        log.info("分配作品成功，作品 ID={}, 评委数={}", dto.getWorkId(), dto.getJudgeIds().size());

        return assignments;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ReviewAssignmentVO> batchAssign(BatchAssignDTO dto, Long creatorId) {
        List<ReviewAssignmentVO> allAssignments = new ArrayList<>();

        for (Long workId : dto.getWorkIds()) {
            AssignWorkDTO assignWorkDTO = new AssignWorkDTO();
            assignWorkDTO.setWorkId(workId);
            assignWorkDTO.setJudgeIds(dto.getJudgeIds());
            List<ReviewAssignmentVO> assignments = assignWork(dto.getContestId(), assignWorkDTO, creatorId);
            allAssignments.addAll(assignments);
        }

        return allAssignments;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public WorkScoreVO score(CreateScoreDTO dto, Long judgeId, Long tenantId) {
        // 验证分配记录是否存在
        ContestWorkAssignment assignment = assignmentMapper.selectById(dto.getAssignmentId());
        if (assignment == null || !assignment.getJudgeId().equals(judgeId)) {
            throw new BusinessException("分配记录不存在");
        }

        if (!assignment.getWorkId().equals(dto.getWorkId())) {
            throw new BusinessException("作品 ID 不匹配");
        }

        // 检查评审时间
        Contest contest = contestMapper.selectById(assignment.getContestId());
        if (contest != null) {
            LocalDateTime now = LocalDateTime.now();
            if (now.isBefore(contest.getReviewStartTime()) || now.isAfter(contest.getReviewEndTime())) {
                throw new BusinessException("不在评审时间范围内");
            }
        }

        // 检查是否已评分
        ContestWorkScore existingScore = scoreMapper.selectOne(new LambdaQueryWrapper<ContestWorkScore>()
                .eq(ContestWorkScore::getAssignmentId, dto.getAssignmentId())
                .eq(ContestWorkScore::getDeleted, 0));
        if (existingScore != null) {
            throw new BusinessException("该作品已评分，请使用更新接口");
        }

        // 获取评委信息
        User judge = userMapper.selectById(judgeId);
        if (judge == null) {
            throw new BusinessException("评委不存在");
        }

        // 创建评分记录
        ContestWorkScore score = new ContestWorkScore();
        score.setTenantId(tenantId);
        score.setContestId(assignment.getContestId());
        score.setWorkId(dto.getWorkId());
        score.setAssignmentId(dto.getAssignmentId());
        score.setJudgeId(judgeId);
        score.setScore(dto.getScore());
        score.setComment(dto.getComment());
        score.setDimensionScores(dto.getDimensionScores());
        score.setCreateBy(judgeId.toString());

        scoreMapper.insert(score);

        // 更新分配状态为已完成
        assignment.setStatus("completed");
        assignment.setCompleteTime(LocalDateTime.now());
        assignmentMapper.updateById(assignment);

        // 更新作品状态为评审中
        ContestWork work = workMapper.selectById(dto.getWorkId());
        if (work != null && !"reviewing".equals(work.getStatus())) {
            work.setStatus("reviewing");
            workMapper.updateById(work);
        }

        log.info("评分成功，分配 ID={}, 分数={}", dto.getAssignmentId(), dto.getScore());

        return convertToScoreVO(score, judge.getNickname());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public WorkScoreVO updateScore(Long scoreId, CreateScoreDTO dto, Long tenantId) {
        ContestWorkScore score = scoreMapper.selectById(scoreId);
        if (score == null || !score.getTenantId().equals(tenantId)) {
            throw new BusinessException("评分记录不存在");
        }

        score.setScore(dto.getScore());
        score.setComment(dto.getComment());
        score.setDimensionScores(dto.getDimensionScores());

        scoreMapper.updateById(score);
        log.info("更新评分成功，ID={}", scoreId);

        return convertToScoreVO(score, null);
    }

    @Override
    public Page<ReviewAssignmentVO> pageQuery(ReviewAssignmentQueryDTO queryDTO, Long tenantId) {
        Page<ContestWorkAssignment> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());

        LambdaQueryWrapper<ContestWorkAssignment> wrapper = new LambdaQueryWrapper<ContestWorkAssignment>()
                .eq(ContestWorkAssignment::getDeleted, 0)
                .eq(queryDTO.getContestId() != null, ContestWorkAssignment::getContestId, queryDTO.getContestId())
                .eq(queryDTO.getWorkId() != null, ContestWorkAssignment::getWorkId, queryDTO.getWorkId())
                .eq(queryDTO.getJudgeId() != null, ContestWorkAssignment::getJudgeId, queryDTO.getJudgeId())
                .eq(queryDTO.getStatus() != null, ContestWorkAssignment::getStatus, queryDTO.getStatus())
                .orderByDesc(ContestWorkAssignment::getAssignTime);

        Page<ContestWorkAssignment> resultPage = assignmentMapper.page(page, wrapper);

        List<ReviewAssignmentVO> voList = resultPage.getRecords().stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());

        Page<ReviewAssignmentVO> voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal());
        voPage.setRecords(voList);
        return voPage;
    }

    @Override
    public List<ReviewAssignmentVO> getMyAssignments(Long judgeId, Long tenantId) {
        List<ContestWorkAssignment> assignments = assignmentMapper.selectList(new LambdaQueryWrapper<ContestWorkAssignment>()
                .eq(ContestWorkAssignment::getJudgeId, judgeId)
                .eq(ContestWorkAssignment::getDeleted, 0)
                .orderByDesc(ContestWorkAssignment::getAssignTime));

        return assignments.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public ReviewStatsVO getStats(Long contestId) {
        LambdaQueryWrapper<ContestWorkAssignment> baseWrapper = new LambdaQueryWrapper<ContestWorkAssignment>()
                .eq(ContestWorkAssignment::getDeleted, 0);
        if (contestId != null) {
            baseWrapper.eq(ContestWorkAssignment::getContestId, contestId);
        }

        long total = assignmentMapper.selectCount(baseWrapper);
        long assigned = assignmentMapper.selectCount(new LambdaQueryWrapper<ContestWorkAssignment>()
                .eq(ContestWorkAssignment::getStatus, "assigned")
                .eq(ContestWorkAssignment::getDeleted, 0)
                .eq(contestId != null, ContestWorkAssignment::getContestId, contestId));
        long reviewing = assignmentMapper.selectCount(new LambdaQueryWrapper<ContestWorkAssignment>()
                .eq(ContestWorkAssignment::getStatus, "reviewing")
                .eq(ContestWorkAssignment::getDeleted, 0)
                .eq(contestId != null, ContestWorkAssignment::getContestId, contestId));
        long completed = assignmentMapper.selectCount(new LambdaQueryWrapper<ContestWorkAssignment>()
                .eq(ContestWorkAssignment::getStatus, "completed")
                .eq(ContestWorkAssignment::getDeleted, 0)
                .eq(contestId != null, ContestWorkAssignment::getContestId, contestId));
        long scored = scoreMapper.selectCount(new LambdaQueryWrapper<ContestWorkScore>()
                .eq(ContestWorkScore::getDeleted, 0)
                .eq(contestId != null, ContestWorkScore::getContestId, contestId));

        ReviewStatsVO vo = new ReviewStatsVO();
        vo.setTotalWorks((int) total);
        vo.setAssigned((int) assigned);
        vo.setReviewing((int) reviewing);
        vo.setCompleted((int) completed);
        vo.setScored((int) scored);
        return vo;
    }

    @Override
    public List<WorkScoreVO> getWorkScores(Long workId, Long tenantId) {
        List<ContestWorkScore> scores = scoreMapper.selectList(new LambdaQueryWrapper<ContestWorkScore>()
                .eq(ContestWorkScore::getWorkId, workId)
                .eq(ContestWorkScore::getTenantId, tenantId)
                .eq(ContestWorkScore::getDeleted, 0)
                .orderByDesc(ContestWorkScore::getCreateTime));

        return scores.stream()
                .map(score -> convertToScoreVO(score, null))
                .collect(Collectors.toList());
    }

    @Override
    public java.math.BigDecimal getAverageScore(Long workId, Long tenantId) {
        List<ContestWorkScore> scores = scoreMapper.selectList(new LambdaQueryWrapper<ContestWorkScore>()
                .eq(ContestWorkScore::getWorkId, workId)
                .eq(ContestWorkScore::getTenantId, tenantId)
                .eq(ContestWorkScore::getDeleted, 0));

        if (scores.isEmpty()) {
            return java.math.BigDecimal.ZERO;
        }

        return scores.stream()
                .map(ContestWorkScore::getScore)
                .reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add)
                .divide(java.math.BigDecimal.valueOf(scores.size()), 2, java.math.BigDecimal.ROUND_HALF_UP);
    }

    // ========== 转换方法 ==========

    private ReviewAssignmentVO convertToVO(ContestWorkAssignment assignment) {
        ReviewAssignmentVO vo = new ReviewAssignmentVO();
        vo.setId(assignment.getId());
        vo.setContestId(assignment.getContestId());
        vo.setWorkId(assignment.getWorkId());
        vo.setJudgeId(assignment.getJudgeId());
        vo.setStatus(assignment.getStatus());
        vo.setAssignTime(assignment.getAssignTime());
        vo.setCompleteTime(assignment.getCompleteTime());

        // 获取作品标题
        ContestWork work = workMapper.selectById(assignment.getWorkId());
        if (work != null) {
            vo.setWorkTitle(work.getTitle());
        }

        // 获取评委姓名
        User judge = userMapper.selectById(assignment.getJudgeId());
        if (judge != null) {
            vo.setJudgeName(judge.getNickname());
        }

        // 获取评分信息
        ContestWorkScore score = scoreMapper.selectOne(new LambdaQueryWrapper<ContestWorkScore>()
                .eq(ContestWorkScore::getAssignmentId, assignment.getId())
                .eq(ContestWorkScore::getDeleted, 0));
        if (score != null) {
            vo.setScoreId(score.getId());
            vo.setScore(score.getScore());
        }

        return vo;
    }

    private WorkScoreVO convertToScoreVO(ContestWorkScore score, String judgeName) {
        WorkScoreVO vo = new WorkScoreVO();
        vo.setId(score.getId());
        vo.setTenantId(score.getTenantId());
        vo.setContestId(score.getContestId());
        vo.setWorkId(score.getWorkId());
        vo.setAssignmentId(score.getAssignmentId());
        vo.setJudgeId(score.getJudgeId());
        vo.setTotalScore(score.getScore());
        vo.setComment(score.getComment());
        vo.setDimensionScores(score.getDimensionScores());
        vo.setCreateTime(score.getCreateTime());

        if (judgeName != null) {
            vo.setJudgeName(judgeName);
        } else {
            User judge = userMapper.selectById(score.getJudgeId());
            if (judge != null) {
                vo.setJudgeName(judge.getNickname());
            }
        }

        return vo;
    }

    @Override
    public String autoAssign(Long contestId, Long creatorId) {
        log.info("开始自动分配作品，活动 ID: {}", contestId);

        // 查询活动所有有效作品（最新版本的）
        List<ContestWork> works = workMapper.selectList(new LambdaQueryWrapper<ContestWork>()
                .eq(ContestWork::getContestId, contestId)
                .eq(ContestWork::getValidState, 1)
                .eq(ContestWork::getIsLatest, true));

        // 查询活动所有有效评委
        List<ContestJudge> judges = judgeMapper.selectList(new LambdaQueryWrapper<ContestJudge>()
                .eq(ContestJudge::getContestId, contestId)
                .eq(ContestJudge::getValidState, 1)
                .eq(ContestJudge::getDeleted, 0));

        if (judges.isEmpty()) {
            throw new BusinessException("该活动没有评委，无法自动分配");
        }

        if (works.isEmpty()) {
            return "没有需要分配的作品";
        }

        int createdCount = 0;
        int judgesPerWork = Math.max(1, 3); // 每个作品分配 3 个评委

        // 轮询分配
        for (int i = 0; i < works.size(); i++) {
            ContestWork work = works.get(i);

            // 查询该作品已分配的评委 ID 列表
            List<Long> assignedJudgeIds = assignmentMapper.selectList(new LambdaQueryWrapper<ContestWorkAssignment>()
                    .eq(ContestWorkAssignment::getWorkId, work.getId())
                    .eq(ContestWorkAssignment::getDeleted, 0))
                    .stream()
                    .map(ContestWorkAssignment::getJudgeId)
                    .collect(Collectors.toList());

            // 为每个作品分配 judgesPerWork 个评委
            for (int j = 0; j < judgesPerWork; j++) {
                int judgeIndex = (i + j) % judges.size();
                ContestJudge judge = judges.get(judgeIndex);

                if (assignedJudgeIds.contains(judge.getJudgeId())) {
                    continue; // 已分配，跳过
                }

                // 检查是否已存在分配记录
                ContestWorkAssignment existing = assignmentMapper.selectOne(new LambdaQueryWrapper<ContestWorkAssignment>()
                        .eq(ContestWorkAssignment::getWorkId, work.getId())
                        .eq(ContestWorkAssignment::getJudgeId, judge.getJudgeId())
                        .eq(ContestWorkAssignment::getDeleted, 0));

                if (existing != null) {
                    continue;
                }

                ContestWorkAssignment assignment = new ContestWorkAssignment();
                assignment.setContestId(contestId);
                assignment.setWorkId(work.getId());
                assignment.setJudgeId(judge.getJudgeId());
                assignment.setStatus("assigned");
                assignment.setAssignTime(LocalDateTime.now());
                if (creatorId != null) {
                    assignment.setCreateBy(creatorId.toString());
                }
                assignmentMapper.insert(assignment);
                createdCount++;
            }
        }

        log.info("自动分配完成，活动 ID={}, 作品数={}, 分配数={}", contestId, works.size(), createdCount);
        return String.format("自动分配完成，共 %d 个作品，创建 %d 条分配记录", works.size(), createdCount);
    }

    @Override
    public ReviewProgressVO getReviewProgress(Long contestId, Long tenantId) {
        log.info("获取评审进度统计，活动 ID: {}", contestId);

        ReviewProgressVO result = new ReviewProgressVO();

        // 活动信息
        Contest contest = contestMapper.selectById(contestId);
        if (contest == null) {
            throw new BusinessException("活动不存在");
        }

        ReviewProgressVO.ContestInfo contestInfo = new ReviewProgressVO.ContestInfo();
        contestInfo.setId(contest.getId());
        contestInfo.setContestName(contest.getContestName());
        contestInfo.setReviewStartTime(contest.getReviewStartTime());
        contestInfo.setReviewEndTime(contest.getReviewEndTime());
        result.setContest(contestInfo);

        // 统计信息
        // 总作品数
        long totalWorks = workMapper.selectCount(new LambdaQueryWrapper<ContestWork>()
                .eq(ContestWork::getContestId, contestId)
                .eq(ContestWork::getValidState, 1)
                .eq(ContestWork::getIsLatest, true));

        // 已分配作品数
        long assignedWorksCount = assignmentMapper.selectCount(new LambdaQueryWrapper<ContestWorkAssignment>()
                .eq(ContestWorkAssignment::getContestId, contestId)
                .eq(ContestWorkAssignment::getDeleted, 0)
                .groupBy(ContestWorkAssignment::getWorkId));

        // 已评分作品数
        long scoredWorksCount = scoreMapper.selectCount(new LambdaQueryWrapper<ContestWorkScore>()
                .eq(ContestWorkScore::getContestId, contestId)
                .eq(ContestWorkScore::getDeleted, 0)
                .groupBy(ContestWorkScore::getWorkId));

        // 评委总数
        long totalJudges = judgeMapper.selectCount(new LambdaQueryWrapper<ContestJudge>()
                .eq(ContestJudge::getContestId, contestId)
                .eq(ContestJudge::getValidState, 1)
                .eq(ContestJudge::getDeleted, 0));

        // 总分配数
        long totalAssignments = assignmentMapper.selectCount(new LambdaQueryWrapper<ContestWorkAssignment>()
                .eq(ContestWorkAssignment::getContestId, contestId)
                .eq(ContestWorkAssignment::getDeleted, 0));

        // 总评分数
        long totalScores = scoreMapper.selectCount(new LambdaQueryWrapper<ContestWorkScore>()
                .eq(ContestWorkScore::getContestId, contestId)
                .eq(ContestWorkScore::getDeleted, 0));

        // 待评分数
        long pendingScoresCount = assignmentMapper.selectCount(new LambdaQueryWrapper<ContestWorkAssignment>()
                .eq(ContestWorkAssignment::getContestId, contestId)
                .eq(ContestWorkAssignment::getStatus, "assigned")
                .eq(ContestWorkAssignment::getDeleted, 0));

        ReviewProgressVO.ReviewSummary summary = new ReviewProgressVO.ReviewSummary();
        summary.setTotalWorks((int) totalWorks);
        summary.setAssignedWorksCount((int) assignedWorksCount);
        summary.setScoredWorksCount((int) scoredWorksCount);
        summary.setUnassignedWorksCount((int) (totalWorks - assignedWorksCount));
        summary.setTotalJudges((int) totalJudges);
        summary.setTotalAssignments((int) totalAssignments);
        summary.setTotalScores((int) totalScores);
        summary.setPendingScoresCount((int) pendingScoresCount);
        result.setSummary(summary);

        // 进度百分比
        ReviewProgressVO.Progress progress = new ReviewProgressVO.Progress();
        progress.setAssignmentProgress(totalWorks > 0 ? (double) assignedWorksCount / totalWorks * 100 : 0);
        progress.setScoringProgress(assignedWorksCount > 0 ? (double) totalScores / (assignedWorksCount * 3) * 100 : 0);
        progress.setOverallProgress(totalWorks > 0 ? (double) scoredWorksCount / totalWorks * 100 : 0);
        result.setProgress(progress);

        // 评委进度（简化）
        result.setJudgeProgress(new ArrayList<>());

        // 待分配作品
        result.setUnassignedWorks(new ArrayList<>());

        // 待评审分配
        result.setPendingAssignments(new ArrayList<>());

        return result;
    }

    @Override
    public WorkStatusStatsVO getWorkStatusStats(Long contestId, Long tenantId) {
        log.info("获取作品状态统计，活动 ID: {}", contestId);

        WorkStatusStatsVO vo = new WorkStatusStatsVO();

        // 总作品数
        long total = workMapper.selectCount(new LambdaQueryWrapper<ContestWork>()
                .eq(ContestWork::getContestId, contestId)
                .eq(ContestWork::getValidState, 1)
                .eq(ContestWork::getIsLatest, true));

        // 已提交
        long submitted = workMapper.selectCount(new LambdaQueryWrapper<ContestWork>()
                .eq(ContestWork::getContestId, contestId)
                .eq(ContestWork::getStatus, "submitted")
                .eq(ContestWork::getValidState, 1)
                .eq(ContestWork::getIsLatest, true));

        // 评审中
        long reviewing = workMapper.selectCount(new LambdaQueryWrapper<ContestWork>()
                .eq(ContestWork::getContestId, contestId)
                .eq(ContestWork::getStatus, "reviewing")
                .eq(ContestWork::getValidState, 1)
                .eq(ContestWork::getIsLatest, true));

        // 已评审
        long reviewed = workMapper.selectCount(new LambdaQueryWrapper<ContestWork>()
                .eq(ContestWork::getContestId, contestId)
                .eq(ContestWork::getStatus, "reviewed")
                .eq(ContestWork::getValidState, 1)
                .eq(ContestWork::getIsLatest, true));

        vo.setTotal((int) total);
        vo.setSubmitted((int) submitted);
        vo.setReviewing((int) reviewing);
        vo.setReviewed((int) reviewed);
        vo.setAwarded(0); // 简化处理

        return vo;
    }

    @Override
    public FinalScoreVO getFinalScore(Long workId, Long tenantId) {
        log.info("获取作品最终得分，作品 ID: {}", workId);

        FinalScoreVO vo = new FinalScoreVO();
        vo.setWorkId(workId);

        // 获取该作品的所有评分
        List<ContestWorkScore> scores = scoreMapper.selectList(new LambdaQueryWrapper<ContestWorkScore>()
                .eq(ContestWorkScore::getWorkId, workId)
                .eq(ContestWorkScore::getTenantId, tenantId)
                .eq(ContestWorkScore::getDeleted, 0));

        if (scores.isEmpty()) {
            vo.setFinalScore(java.math.BigDecimal.ZERO);
            vo.setScoreCount(0);
            vo.setCalculationRule("average");
            return vo;
        }

        // 计算平均分
        java.math.BigDecimal totalScore = scores.stream()
                .map(ContestWorkScore::getScore)
                .reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add);

        java.math.BigDecimal avgScore = totalScore.divide(
                java.math.BigDecimal.valueOf(scores.size()), 2, java.math.BigDecimal.ROUND_HALF_UP);

        vo.setFinalScore(avgScore);
        vo.setScoreCount(scores.size());
        vo.setCalculationRule("average");
        vo.setRank(0); // 简化处理，实际需要计算排名

        return vo;
    }

    @Override
    public void replaceJudge(Long assignmentId, Long newJudgeId, Long tenantId) {
        log.info("替换评委，分配 ID: {}, 新评委 ID: {}", assignmentId, newJudgeId);

        ContestWorkAssignment assignment = assignmentMapper.selectById(assignmentId);
        if (assignment == null) {
            throw new BusinessException("分配记录不存在");
        }

        // 检查新评委是否是该活动的评委
        ContestJudge judge = judgeMapper.selectOne(new LambdaQueryWrapper<ContestJudge>()
                .eq(ContestJudge::getContestId, assignment.getContestId())
                .eq(ContestJudge::getJudgeId, newJudgeId)
                .eq(ContestJudge::getValidState, 1)
                .eq(ContestJudge::getDeleted, 0));

        if (judge == null) {
            throw new BusinessException("该用户不是该活动的评委");
        }

        // 删除原分配记录
        assignment.setDeleted(1);
        assignmentMapper.updateById(assignment);

        // 创建新分配记录
        ContestWorkAssignment newAssignment = new ContestWorkAssignment();
        newAssignment.setContestId(assignment.getContestId());
        newAssignment.setWorkId(assignment.getWorkId());
        newAssignment.setJudgeId(newJudgeId);
        newAssignment.setStatus("assigned");
        newAssignment.setAssignTime(LocalDateTime.now());
        assignmentMapper.insert(newAssignment);

        log.info("评委替换成功");
    }

    @Override
    public List<JudgeContestVO> getJudgeContests(Long judgeId, Long tenantId) {
        log.info("获取评委参与的活动列表，评委 ID: {}", judgeId);

        // 查询该评委参与的活动 ID 列表
        List<ContestJudge> contestJudges = judgeMapper.selectList(new LambdaQueryWrapper<ContestJudge>()
                .eq(ContestJudge::getJudgeId, judgeId)
                .eq(ContestJudge::getValidState, 1)
                .eq(ContestJudge::getDeleted, 0));

        List<JudgeContestVO> result = new ArrayList<>();
        for (ContestJudge contestJudge : contestJudges) {
            Contest contest = contestMapper.selectById(contestJudge.getContestId());
            if (contest == null) {
                continue;
            }

            JudgeContestVO vo = new JudgeContestVO();
            vo.setId(contest.getId());
            vo.setContestName(contest.getContestName());
            vo.setStatus(contest.getStatus());
            vo.setReviewStartTime(contest.getReviewStartTime());
            vo.setReviewEndTime(contest.getReviewEndTime());

            // 统计该评委在该活动中的作品分配情况
            long assignedCount = assignmentMapper.selectCount(new LambdaQueryWrapper<ContestWorkAssignment>()
                    .eq(ContestWorkAssignment::getContestId, contest.getId())
                    .eq(ContestWorkAssignment::getJudgeId, judgeId)
                    .eq(ContestWorkAssignment::getDeleted, 0));

            long scoredCount = scoreMapper.selectCount(new LambdaQueryWrapper<ContestWorkScore>()
                    .eq(ContestWorkScore::getContestId, contest.getId())
                    .eq(ContestWorkScore::getJudgeId, judgeId)
                    .eq(ContestWorkScore::getDeleted, 0));

            vo.setAssignedWorksCount((int) assignedCount);
            vo.setScoredWorksCount((int) scoredCount);
            vo.setPendingWorksCount((int) (assignedCount - scoredCount));

            result.add(vo);
        }

        return result;
    }

    @Override
    public Page<JudgeWorkVO> getJudgeContestWorks(Long contestId, Long judgeId, Long tenantId, JudgeWorkQueryDTO queryDTO) {
        log.info("获取评委在某个活动下的作品列表，活动 ID: {}, 评委 ID: {}", contestId, judgeId);

        Page<ContestWorkAssignment> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());

        // 查询该评委在该活动中的分配记录
        LambdaQueryWrapper<ContestWorkAssignment> wrapper = new LambdaQueryWrapper<ContestWorkAssignment>()
                .eq(ContestWorkAssignment::getContestId, contestId)
                .eq(ContestWorkAssignment::getJudgeId, judgeId)
                .eq(ContestWorkAssignment::getDeleted, 0)
                .orderByDesc(ContestWorkAssignment::getAssignTime);

        Page<ContestWorkAssignment> resultPage = assignmentMapper.page(page, wrapper);

        List<JudgeWorkVO> voList = new ArrayList<>();
        for (ContestWorkAssignment assignment : resultPage.getRecords()) {
            JudgeWorkVO vo = new JudgeWorkVO();
            vo.setId(assignment.getWorkId());
            vo.setAssignmentStatus(assignment.getStatus());
            vo.setAssignmentTime(assignment.getAssignTime());

            // 获取作品信息
            ContestWork work = workMapper.selectById(assignment.getWorkId());
            if (work != null) {
                vo.setWorkNo(work.getWorkNo());
                vo.setTitle(work.getTitle());
            }

            // 获取评分信息
            ContestWorkScore score = scoreMapper.selectOne(new LambdaQueryWrapper<ContestWorkScore>()
                    .eq(ContestWorkScore::getAssignmentId, assignment.getId())
                    .eq(ContestWorkScore::getDeleted, 0));
            if (score != null) {
                vo.setScoreStatus("scored");
                vo.setScore(score.getScore());
                vo.setComments(score.getComment());
            } else {
                vo.setScoreStatus("pending");
            }

            // 获取参赛者信息
            if (work != null) {
                ContestRegistration registration = registrationMapper.selectById(work.getRegistrationId());
                if (registration != null) {
                    vo.setParticipantName(registration.getAccountName());
                    vo.setParticipantType("team".equals(registration.getRegistrationType()) ? "team" : "personal");
                }
            }

            voList.add(vo);
        }

        Page<JudgeWorkVO> voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal());
        voPage.setRecords(voList);
        return voPage;
    }
}
