import {
  Injectable,
  NotFoundException,
  BadRequestException,
} from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import { SetAwardDto } from './dto/set-award.dto';
import { BatchSetAwardsDto } from './dto/batch-set-awards.dto';
import { QueryResultsDto } from './dto/query-results.dto';

@Injectable()
export class ResultsService {
  constructor(private prisma: PrismaService) {}

  /**
   * 计算活动所有作品的最终得分
   */
  async calculateAllFinalScores(contestId: number) {
    // 验证活动是否存在
    const contest = await this.prisma.contest.findUnique({
      where: { id: contestId },
      include: {
        reviewRule: true,
      },
    });

    if (!contest) {
      throw new NotFoundException('活动不存在');
    }

    // 获取所有有效作品
    const works = await this.prisma.contestWork.findMany({
      where: {
        contestId,
        validState: 1,
        isLatest: true,
      },
      include: {
        scores: {
          where: { validState: 1 },
        },
      },
    });

    if (works.length === 0) {
      return {
        message: '没有需要计算的作品',
        calculatedCount: 0,
      };
    }

    const calculationRule = contest.reviewRule?.calculationRule || 'average';
    let calculatedCount = 0;

    // 获取评委权重（用于加权平均）
    const judges = await this.prisma.contestJudge.findMany({
      where: {
        contestId,
        validState: 1,
      },
    });
    const judgeWeights = new Map<number, number>(
      judges.map((j) => [j.judgeId, Number(j.weight || 1)]),
    );

    for (const work of works) {
      if (work.scores.length === 0) {
        continue;
      }

      const scores = work.scores.map((s) => Number(s.totalScore));
      let finalScore = 0;

      switch (calculationRule) {
        case 'average':
          finalScore = scores.reduce((a, b) => a + b, 0) / scores.length;
          break;
        case 'max':
          finalScore = Math.max(...scores);
          break;
        case 'min':
          finalScore = Math.min(...scores);
          break;
        case 'weighted':
          let totalWeight = 0;
          let weightedSum = 0;

          work.scores.forEach((score) => {
            const weight = judgeWeights.get(score.judgeId) || 1;
            weightedSum += Number(score.totalScore) * weight;
            totalWeight += weight;
          });

          finalScore = totalWeight > 0 ? weightedSum / totalWeight : 0;
          break;
        default:
          finalScore = scores.reduce((a, b) => a + b, 0) / scores.length;
      }

      await this.prisma.contestWork.update({
        where: { id: work.id },
        data: {
          finalScore: Number(finalScore.toFixed(2)),
        },
      });

      calculatedCount++;
    }

    return {
      message: `成功计算 ${calculatedCount} 件作品的最终得分`,
      calculatedCount,
      calculationRule,
    };
  }

  /**
   * 计算排名
   */
  async calculateRankings(contestId: number) {
    // 验证活动是否存在
    const contest = await this.prisma.contest.findUnique({
      where: { id: contestId },
    });

    if (!contest) {
      throw new NotFoundException('活动不存在');
    }

    // 获取所有有最终得分的作品，按得分降序排列
    const works = await this.prisma.contestWork.findMany({
      where: {
        contestId,
        validState: 1,
        isLatest: true,
        finalScore: { not: null },
      },
      orderBy: {
        finalScore: 'desc',
      },
    });

    if (works.length === 0) {
      return {
        message: '没有需要排名的作品，请先计算最终得分',
        rankedCount: 0,
      };
    }

    // 计算排名（同分同名次）
    let currentRank = 1;
    let previousScore: number | null = null;
    let sameScoreCount = 0;

    for (let i = 0; i < works.length; i++) {
      const work = works[i];
      const currentScore = Number(work.finalScore);

      if (previousScore !== null && currentScore === previousScore) {
        // 同分，保持相同排名
        sameScoreCount++;
      } else {
        // 不同分，更新排名（跳过同分数量）
        currentRank = i + 1;
        sameScoreCount = 0;
      }

      await this.prisma.contestWork.update({
        where: { id: work.id },
        data: {
          rank: currentRank,
        },
      });

      previousScore = currentScore;
    }

    return {
      message: `成功计算 ${works.length} 件作品的排名`,
      rankedCount: works.length,
    };
  }

  /**
   * 设置单个作品奖项
   */
  async setAward(workId: number, setAwardDto: SetAwardDto) {
    const work = await this.prisma.contestWork.findUnique({
      where: { id: workId },
    });

    if (!work) {
      throw new NotFoundException('作品不存在');
    }

    return this.prisma.contestWork.update({
      where: { id: workId },
      data: {
        awardLevel: setAwardDto.awardLevel,
        awardName: setAwardDto.awardName,
        certificateUrl: setAwardDto.certificateUrl,
        status: 'awarded',
      },
      include: {
        registration: {
          include: {
            user: {
              select: {
                id: true,
                username: true,
                nickname: true,
              },
            },
            team: {
              select: {
                id: true,
                teamName: true,
              },
            },
          },
        },
      },
    });
  }

  /**
   * 批量设置奖项
   */
  async batchSetAwards(contestId: number, batchSetAwardsDto: BatchSetAwardsDto) {
    // 验证活动是否存在
    const contest = await this.prisma.contest.findUnique({
      where: { id: contestId },
    });

    if (!contest) {
      throw new NotFoundException('活动不存在');
    }

    const results = [];

    for (const award of batchSetAwardsDto.awards) {
      const work = await this.prisma.contestWork.findFirst({
        where: {
          id: award.workId,
          contestId,
          validState: 1,
        },
      });

      if (!work) {
        results.push({
          workId: award.workId,
          success: false,
          error: '作品不存在',
        });
        continue;
      }

      await this.prisma.contestWork.update({
        where: { id: award.workId },
        data: {
          awardLevel: award.awardLevel,
          awardName: award.awardName,
          status: 'awarded',
        },
      });

      results.push({
        workId: award.workId,
        success: true,
      });
    }

    return {
      message: `批量设置完成`,
      total: batchSetAwardsDto.awards.length,
      successCount: results.filter((r) => r.success).length,
      failedCount: results.filter((r) => !r.success).length,
      results,
    };
  }

  /**
   * 根据排名自动设置奖项
   */
  async autoSetAwards(
    contestId: number,
    awardConfig: {
      first?: number;
      second?: number;
      third?: number;
      excellent?: number;
    },
  ) {
    const contest = await this.prisma.contest.findUnique({
      where: { id: contestId },
    });

    if (!contest) {
      throw new NotFoundException('活动不存在');
    }

    // 获取已排名的作品
    const works = await this.prisma.contestWork.findMany({
      where: {
        contestId,
        validState: 1,
        isLatest: true,
        rank: { not: null },
      },
      orderBy: {
        rank: 'asc',
      },
    });

    if (works.length === 0) {
      throw new BadRequestException('没有已排名的作品，请先计算排名');
    }

    const firstCount = awardConfig.first || 0;
    const secondCount = awardConfig.second || 0;
    const thirdCount = awardConfig.third || 0;
    const excellentCount = awardConfig.excellent || 0;

    let assignedCount = 0;
    const awards: { workId: number; awardLevel: string; awardName: string }[] = [];

    for (let i = 0; i < works.length; i++) {
      const work = works[i];
      let awardLevel: string | null = null;
      let awardName: string | null = null;

      if (i < firstCount) {
        awardLevel = 'first';
        awardName = '一等奖';
      } else if (i < firstCount + secondCount) {
        awardLevel = 'second';
        awardName = '二等奖';
      } else if (i < firstCount + secondCount + thirdCount) {
        awardLevel = 'third';
        awardName = '三等奖';
      } else if (i < firstCount + secondCount + thirdCount + excellentCount) {
        awardLevel = 'excellent';
        awardName = '优秀奖';
      }

      if (awardLevel) {
        await this.prisma.contestWork.update({
          where: { id: work.id },
          data: {
            awardLevel,
            awardName,
            status: 'awarded',
          },
        });

        awards.push({
          workId: work.id,
          awardLevel,
          awardName,
        });

        assignedCount++;
      }
    }

    return {
      message: `自动设置奖项完成`,
      assignedCount,
      awards,
    };
  }

  /**
   * 发布成果
   */
  async publishResults(contestId: number) {
    const contest = await this.prisma.contest.findUnique({
      where: { id: contestId },
    });

    if (!contest) {
      throw new NotFoundException('活动不存在');
    }

    if (contest.resultState === 'published') {
      throw new BadRequestException('成果已发布');
    }

    // 检查是否有已排名的作品
    const rankedWorks = await this.prisma.contestWork.count({
      where: {
        contestId,
        validState: 1,
        isLatest: true,
        rank: { not: null },
      },
    });

    if (rankedWorks === 0) {
      throw new BadRequestException('没有已排名的作品，请先计算排名');
    }

    // 更新活动状态
    const updatedContest = await this.prisma.contest.update({
      where: { id: contestId },
      data: {
        resultState: 'published',
        resultPublishTime: new Date(),
        status: 'finished',
      },
    });

    return {
      message: '成果发布成功',
      contest: updatedContest,
      publishTime: updatedContest.resultPublishTime,
    };
  }

  /**
   * 撤回发布
   */
  async unpublishResults(contestId: number) {
    const contest = await this.prisma.contest.findUnique({
      where: { id: contestId },
    });

    if (!contest) {
      throw new NotFoundException('活动不存在');
    }

    if (contest.resultState !== 'published') {
      throw new BadRequestException('成果未发布');
    }

    const updatedContest = await this.prisma.contest.update({
      where: { id: contestId },
      data: {
        resultState: 'unpublished',
        resultPublishTime: null,
      },
    });

    return {
      message: '已撤回成果发布',
      contest: updatedContest,
    };
  }

  /**
   * 获取活动结果列表（作品列表）
   */
  async getResults(contestId: number, queryDto: QueryResultsDto) {
    const { page = 1, pageSize = 10, workNo, accountNo } = queryDto;

    const contest = await this.prisma.contest.findUnique({
      where: { id: contestId },
      include: {
        reviewRule: true,
      },
    });

    if (!contest) {
      throw new NotFoundException('活动不存在');
    }

    const skip = (page - 1) * pageSize;

    // 构建查询条件
    const where: any = {
      contestId,
      validState: 1,
      isLatest: true,
    };

    // 作品编号搜索
    if (workNo) {
      where.workNo = { contains: workNo };
    }

    // 报名账号搜索（需要关联查询）
    if (accountNo) {
      where.registration = {
        user: {
          username: { contains: accountNo },
        },
      };
    }

    const [works, total] = await Promise.all([
      this.prisma.contestWork.findMany({
        where,
        include: {
          registration: {
            include: {
              user: {
                include: {
                  tenant: {
                    select: {
                      id: true,
                      name: true,
                    },
                  },
                  student: {
                    include: {
                      class: {
                        include: {
                          grade: {
                            select: {
                              id: true,
                              name: true,
                            },
                          },
                        },
                      },
                    },
                  },
                },
              },
              team: {
                select: {
                  id: true,
                  teamName: true,
                },
              },
              teachers: {
                include: {
                  user: {
                    select: {
                      id: true,
                      username: true,
                      nickname: true,
                    },
                  },
                },
              },
            },
          },
          scores: {
            where: { validState: 1 },
            select: {
              id: true,
              totalScore: true,
              judgeName: true,
              scoreTime: true,
            },
          },
        },
        orderBy: [
          { finalScore: 'desc' },
        ],
        skip,
        take: pageSize,
      }),
      this.prisma.contestWork.count({ where }),
    ]);

    // 计算每个作品的评委平均分（用于显示）
    const enrichedWorks = works.map((work) => {
      let judgeScore: number | null = work.finalScore
        ? Number(work.finalScore)
        : null;
      // 如果没有最终得分但有评分记录，则计算平均分作为评委评分
      if (judgeScore === null && work.scores && work.scores.length > 0) {
        const totalScores = work.scores.reduce(
          (sum, s) => sum + Number(s.totalScore),
          0,
        );
        judgeScore = Number((totalScores / work.scores.length).toFixed(2));
      }
      return {
        ...work,
        judgeScore, // 评委评分（平均分）
      };
    });

    return {
      contest: {
        id: contest.id,
        contestName: contest.contestName,
        resultState: contest.resultState,
        resultPublishTime: contest.resultPublishTime,
      },
      list: enrichedWorks,
      total,
      page,
      pageSize,
    };
  }

  /**
   * 获取活动结果统计摘要
   */
  async getResultsSummary(contestId: number) {
    const contest = await this.prisma.contest.findUnique({
      where: { id: contestId },
    });

    if (!contest) {
      throw new NotFoundException('活动不存在');
    }

    // 获取总作品数
    const totalWorks = await this.prisma.contestWork.count({
      where: {
        contestId,
        validState: 1,
        isLatest: true,
      },
    });

    // 获取已计分作品数
    const scoredWorks = await this.prisma.contestWork.count({
      where: {
        contestId,
        validState: 1,
        isLatest: true,
        finalScore: { not: null },
      },
    });

    // 获取已排名作品数
    const rankedWorks = await this.prisma.contestWork.count({
      where: {
        contestId,
        validState: 1,
        isLatest: true,
        rank: { not: null },
      },
    });

    // 获取已设奖作品数
    const awardedWorks = await this.prisma.contestWork.count({
      where: {
        contestId,
        validState: 1,
        isLatest: true,
        awardLevel: { not: null },
      },
    });

    // 奖项分布
    const awardStats = await this.prisma.contestWork.groupBy({
      by: ['awardLevel'],
      where: {
        contestId,
        validState: 1,
        isLatest: true,
        awardLevel: { not: null },
      },
      _count: {
        id: true,
      },
    });

    const awardDistribution: Record<string, number> = {
      first: 0,
      second: 0,
      third: 0,
      excellent: 0,
    };
    awardStats.forEach((stat) => {
      if (stat.awardLevel) {
        awardDistribution[stat.awardLevel] = stat._count.id;
      }
    });

    // 获取分数统计
    const scoreStats = await this.prisma.contestWork.aggregate({
      where: {
        contestId,
        validState: 1,
        isLatest: true,
        finalScore: { not: null },
      },
      _avg: { finalScore: true },
      _max: { finalScore: true },
      _min: { finalScore: true },
    });

    return {
      contest: {
        id: contest.id,
        contestName: contest.contestName,
        resultState: contest.resultState,
        resultPublishTime: contest.resultPublishTime,
      },
      summary: {
        totalWorks,
        scoredWorks,
        rankedWorks,
        awardedWorks,
        unscoredWorks: totalWorks - scoredWorks,
      },
      awardDistribution,
      scoreStats: {
        avgScore: scoreStats._avg.finalScore
          ? Number(scoreStats._avg.finalScore).toFixed(2)
          : null,
        maxScore: scoreStats._max.finalScore
          ? Number(scoreStats._max.finalScore).toFixed(2)
          : null,
        minScore: scoreStats._min.finalScore
          ? Number(scoreStats._min.finalScore).toFixed(2)
          : null,
      },
    };
  }
}
