import "server-only"

import { cache } from "react"
import { getTranslations } from "next-intl/server"

import { db } from "@/shared/db"
import { exams, examQuestions } from "@/shared/db/schema"
import { isRecord } from "@/shared/lib/type-guards"
import { eq } from "drizzle-orm"
import {
  getHomeworkAssignmentsByExamId,
  getGradedSubmissionsByExamId,
} from "@/modules/homework/data-access-exam-cross"
import { getQuestionText } from "@/modules/homework/data-access-utils"

const parseExamMeta = (description: string | null): Record<string, unknown> => {
  if (!description) return {}
  try {
    const parsed: unknown = JSON.parse(description)
    return isRecord(parsed) ? parsed : {}
  } catch {
    return {}
  }
}

const getNumber = (obj: Record<string, unknown>, key: string): number | undefined => {
  const v = obj[key]
  return typeof v === "number" ? v : undefined
}

/**
 * V3-8: 考试分析数据类型
 */
export interface ExamAnalyticsSummary {
  examId: string
  examTitle: string
  totalScore: number
  assignmentCount: number
  totalStudents: number
  submittedCount: number
  gradedCount: number
  averageScore: number
  maxScore: number
  passRate: number
  scoreDistribution: Array<{ range: string; count: number }>
  questions: Array<{
    questionId: string
    questionType: string
    questionText: string
    maxScore: number
    errorCount: number
    errorRate: number
    difficulty: "easy" | "medium" | "hard"
  }>
}

/**
 * V3-8: 获取考试分析数据
 *
 * 对标智学网考试分析功能，聚合该考试所有作业的已批改提交数据，
 * 计算：平均分、及格率、分数段分布、逐题错误率与难度。
 */
export const getExamAnalytics = cache(async (examId: string): Promise<ExamAnalyticsSummary | null> => {
  const t = await getTranslations("examHomework")
  const exam = await db.query.exams.findFirst({
    where: eq(exams.id, examId),
    columns: { id: true, title: true, description: true },
  })

  if (!exam) return null

  const meta = parseExamMeta(exam.description)
  const examTotalScore = getNumber(meta, "totalScore") ?? 100

  const [assignments, gradedSubmissions, examQuestionsList] = await Promise.all([
    getHomeworkAssignmentsByExamId(examId),
    getGradedSubmissionsByExamId(examId),
    db.query.examQuestions.findMany({
      where: eq(examQuestions.examId, examId),
      with: { question: true },
      orderBy: (eqRel, { asc }) => [asc(eqRel.order)],
    }),
  ])

  const totalStudents = assignments.reduce((sum, a) => sum + a.targetCount, 0)
  const submittedCount = assignments.reduce((sum, a) => sum + a.submittedCount, 0)
  const gradedCount = gradedSubmissions.length

  // Calculate max score from exam questions
  const maxScore = examQuestionsList.reduce((sum, eq) => sum + (eq.score ?? 0), 0)

  // Average score and pass rate
  const scores = gradedSubmissions.map((s) => s.score)
  const averageScore = scores.length > 0 ? scores.reduce((a, b) => a + b, 0) / scores.length : 0
  const passThreshold = maxScore * 0.6
  const passCount = scores.filter((s) => s >= passThreshold).length
  const passRate = scores.length > 0 ? passCount / scores.length : 0

  // Score distribution (0-59, 60-69, 70-79, 80-89, 90-100)
  const ranges = [
    { range: "0-59%", min: 0, max: 0.59 },
    { range: "60-69%", min: 0.6, max: 0.69 },
    { range: "70-79%", min: 0.7, max: 0.79 },
    { range: "80-89%", min: 0.8, max: 0.89 },
    { range: "90-100%", min: 0.9, max: 1.0 },
  ]
  const scoreDistribution = ranges.map((r) => {
    const count = scores.filter((s) => {
      const pct = maxScore > 0 ? s / maxScore : 0
      return pct >= r.min && pct <= r.max
    }).length
    return { range: r.range, count }
  })

  // Per-question error rate and difficulty
  const questions: ExamAnalyticsSummary["questions"] = examQuestionsList.map((eq) => {
    const questionId = eq.questionId
    const maxScore = eq.score ?? 0
    let errorCount = 0
    let totalAttempted = 0

    for (const sub of gradedSubmissions) {
      const ans = sub.answers.find((a) => a.questionId === questionId)
      if (!ans) continue
      totalAttempted += 1
      if (ans.score < maxScore) {
        errorCount += 1
      }
    }

    const errorRate = totalAttempted > 0 ? errorCount / totalAttempted : 0
    const difficulty: "easy" | "medium" | "hard" =
      errorRate < 0.3 ? "easy" : errorRate < 0.7 ? "medium" : "hard"

    return {
      questionId,
      questionType: eq.question.type,
      questionText: getQuestionText(eq.question.content) || t("exam.actionMessages.noQuestionText"),
      maxScore,
      errorCount,
      errorRate,
      difficulty,
    }
  })

  return {
    examId: exam.id,
    examTitle: exam.title,
    totalScore: examTotalScore,
    assignmentCount: assignments.length,
    totalStudents,
    submittedCount,
    gradedCount,
    averageScore: Math.round(averageScore * 100) / 100,
    maxScore,
    passRate: Math.round(passRate * 100) / 100,
    scoreDistribution,
    questions,
  }
})
