"use server";

import prisma from "@/lib/prisma";
import { getLocale } from "next-intl/server";
import { Locale, Status, ProblemLocalization } from "@/generated/client";
import { assertTeacherOrAdmin, getAuthenticatedActor } from "./course-auth";

const getLocalizedTitle = (
  localizations: ProblemLocalization[],
  locale: Locale
) => {
  if (!localizations || localizations.length === 0) {
    return "Unknown Title";
  }

  const localization = localizations.find(
    (localization) => localization.locale === locale
  );

  return localization?.content ?? localizations[0].content ?? "Unknown Title";
};

export interface ProblemCompletionData {
  problemId: string;
  problemDisplayId: number;
  problemTitle: string;
  completed: number;
  uncompleted: number;
  total: number;
  completedPercent: number;
  uncompletedPercent: number;
}

export interface DifficultProblemData {
  id: string;
  className: string;
  problemCount: number;
  problemTitle: string;
  problemDisplayId: number;
}

export async function getProblemCompletionData(): Promise<
  ProblemCompletionData[]
> {
  const actor = await getAuthenticatedActor();
  assertTeacherOrAdmin(actor);

  // 获取所有提交记录，按题目分组统计
  const submissions = await prisma.submission.findMany({
    include: {
      user: true,
      problem: {
        include: {
          localizations: true,
        },
      },
    },
  });

  const locale = await getLocale();

  // 按题目分组统计完成情况（统计独立用户数）
  const problemStats = new Map<
    string,
    {
      completedUsers: Set<string>;
      totalUsers: Set<string>;
      title: string;
      displayId: number;
    }
  >();

  submissions.forEach((submission) => {
    const localizations = submission.problem.localizations;
    const title = getLocalizedTitle(localizations, locale as Locale);
    const problemId = submission.problemId;
    const problemTitle = title;
    const problemDisplayId = submission.problem.displayId;
    const userId = submission.userId;
    const isCompleted = submission.status === Status.AC; // 只有 Accepted 才算完成

    if (!problemStats.has(problemId)) {
      problemStats.set(problemId, {
        completedUsers: new Set(),
        totalUsers: new Set(),
        title: problemTitle,
        displayId: problemDisplayId,
      });
    }

    const stats = problemStats.get(problemId)!;
    stats.totalUsers.add(userId);
    if (isCompleted) {
      stats.completedUsers.add(userId);
    }
  });

  // 如果没有数据，返回空数组
  if (problemStats.size === 0) {
    return [];
  }

  // 转换为图表数据格式，按题目displayId排序
  const problemDataArray = Array.from(problemStats.entries()).map(
    ([problemId, stats]) => {
      const completed = stats.completedUsers.size;
      const total = stats.totalUsers.size;

      return {
        problemId: problemId,
        problemDisplayId: stats.displayId,
        problemTitle: stats.title,
        completed: completed,
        uncompleted: total - completed,
        total: total,
        completedPercent: total > 0 ? (completed / total) * 100 : 0,
        uncompletedPercent: total > 0 ? ((total - completed) / total) * 100 : 0,
      };
    }
  );

  // 按题目编号排序
  return problemDataArray.sort(
    (a, b) => a.problemDisplayId - b.problemDisplayId
  );
}

export async function getDifficultProblemsData(): Promise<
  DifficultProblemData[]
> {
  const actor = await getAuthenticatedActor();
  assertTeacherOrAdmin(actor);

  // 获取所有用例级判题结果
  const judgeRuns = await prisma.judgeRun.findMany({
    include: {
      testcase: {
        include: {
          problem: {
            include: {
              localizations: true,
            },
          },
        },
      },
      judge: {
        include: {
          submission: {
            include: {
              user: true,
            },
          },
        },
      },
    },
  });

  // 按问题分组统计错误率
  const problemStats = new Map<
    string,
    {
      totalAttempts: number;
      wrongAttempts: number;
      title: string;
      displayId: number;
      users: Set<string>;
    }
  >();

  judgeRuns.forEach((result) => {
    const problemId = result.testcase.problemId;
    const problemTitle =
      result.testcase.problem.localizations?.find((loc) => loc.type === "TITLE")
        ?.content || "无标题";
    const problemDisplayId = result.testcase.problem.displayId;
    const userId = result.judge.submission.userId;
    const isWrong = result.status !== "ACCEPTED";

    if (!problemStats.has(problemId)) {
      problemStats.set(problemId, {
        totalAttempts: 0,
        wrongAttempts: 0,
        title: problemTitle,
        displayId: problemDisplayId,
        users: new Set(),
      });
    }

    const stats = problemStats.get(problemId)!;
    stats.totalAttempts++;
    stats.users.add(userId);
    if (isWrong) {
      stats.wrongAttempts++;
    }
  });

  // 计算错误率并筛选易错题（错误率 > 30% 且至少有3次尝试）
  const difficultProblems = Array.from(problemStats.entries())
    .map(([problemId, stats]) => ({
      id: problemId,
      className: `题目 ${stats.title}`,
      problemCount: stats.wrongAttempts,
      problemTitle: stats.title,
      problemDisplayId: stats.displayId,
      errorRate: (stats.wrongAttempts / stats.totalAttempts) * 100,
      uniqueUsers: stats.users.size,
      totalAttempts: stats.totalAttempts,
    }))
    .filter(
      (problem) =>
        problem.errorRate > 30 && // 错误率超过30%
        problem.totalAttempts >= 3 // 至少有3次尝试
    )
    .sort((a, b) => b.errorRate - a.errorRate) // 按错误率降序排列
    .slice(0, 10); // 取前10个最难的题目

  return difficultProblems;
}

export async function getDashboardStats() {
  const actor = await getAuthenticatedActor();
  assertTeacherOrAdmin(actor);

  const [problemData, difficultProblems] = await Promise.all([
    getProblemCompletionData(),
    getDifficultProblemsData(),
  ]);

  return {
    problemData,
    difficultProblems,
    totalProblems: problemData.length,
    totalDifficultProblems: difficultProblems.length,
  };
}
