import "server-only"

import { cache } from "react"
import { and, count, desc, eq, inArray, sql } from "drizzle-orm"

import { db } from "@/shared/db"
import { practiceAnswers, practiceSessions, questions, questionsToKnowledgePoints, knowledgePoints } from "@/shared/db/schema"
import {
  getActiveStudentIdsByClassId,
  getClassNamesByIds,
  getClassNameById,
  getClassesByGradeId,
} from "@/modules/classes/data-access"
import { getUserIdsByGradeId, getUserNamesByIds } from "@/modules/users/data-access"

// ---------------------------------------------------------------------------
// 类型定义
// ---------------------------------------------------------------------------

/** 班级专项练习统计 */
export interface ClassPracticeStats {
  classId: string
  className: string
  totalSessions: number
  completedSessions: number
  totalQuestionsAnswered: number
  totalCorrect: number
  averageAccuracy: number
  /** 参与练习的学生数 */
  activeStudents: number
}

/** 学生专项练习摘要 */
export interface StudentPracticeSummary {
  studentId: string
  studentName: string | null
  totalSessions: number
  completedSessions: number
  totalQuestionsAnswered: number
  totalCorrect: number
  accuracy: number
  lastPracticeAt: Date | null
}

/** 按练习类型分组的统计 */
export interface PracticeTypeBreakdown {
  practiceType: string
  sessionCount: number
  totalQuestions: number
  correctCount: number
  accuracy: number
}

// ---------------------------------------------------------------------------
// 查询函数
// ---------------------------------------------------------------------------

/**
 * 获取班级专项练习统计。
 *
 * 汇总班级所有学生的练习数据，包括会话数、完成数、正确率等。
 * 使用单条 SQL 同时计算汇总统计与活跃学生数（COUNT(DISTINCT)），
 * 避免 N+1 查询。
 *
 * @param classId 班级 ID
 */
export const getClassPracticeStats = cache(async (
  classId: string,
): Promise<ClassPracticeStats | null> => {
  const studentIds = await getActiveStudentIdsByClassId(classId)
  if (studentIds.length === 0) return null

  // 单条 SQL 同时获取汇总统计与活跃学生数（替代原先两条 SQL）
  const rows = await db
    .select({
      totalSessions: count(),
      completedSessions: count(sql`CASE WHEN ${practiceSessions.status} = 'completed' THEN 1 END`),
      totalQuestionsAnswered: sql<number>`COALESCE(SUM(${practiceSessions.answeredQuestions}), 0)`,
      totalCorrect: sql<number>`COALESCE(SUM(${practiceSessions.correctCount}), 0)`,
      activeStudents: sql<number>`COUNT(DISTINCT ${practiceSessions.studentId})`,
    })
    .from(practiceSessions)
    .where(inArray(practiceSessions.studentId, studentIds))

  const row = rows[0]
  if (!row) return null

  const totalQuestionsAnswered = Number(row.totalQuestionsAnswered)
  const totalCorrect = Number(row.totalCorrect)
  const activeStudents = Number(row.activeStudents)

  return {
    classId,
    className: "", // 由调用方填充
    totalSessions: Number(row.totalSessions),
    completedSessions: Number(row.completedSessions),
    totalQuestionsAnswered,
    totalCorrect,
    averageAccuracy: totalQuestionsAnswered > 0 ? totalCorrect / totalQuestionsAnswered : 0,
    activeStudents,
  }
})

/**
 * 获取班级所有学生的专项练习摘要。
 *
 * @param classId 班级 ID
 */
export const getClassStudentPracticeSummaries = cache(async (
  classId: string,
): Promise<StudentPracticeSummary[]> => {
  const studentIds = await getActiveStudentIdsByClassId(classId)
  if (studentIds.length === 0) return []

  const rows = await db
    .select({
      studentId: practiceSessions.studentId,
      totalSessions: count(),
      completedSessions: count(sql`CASE WHEN ${practiceSessions.status} = 'completed' THEN 1 END`),
      totalQuestionsAnswered: sql<number>`COALESCE(SUM(${practiceSessions.answeredQuestions}), 0)`,
      totalCorrect: sql<number>`COALESCE(SUM(${practiceSessions.correctCount}), 0)`,
      lastPracticeAt: sql<Date | null>`MAX(${practiceSessions.startedAt})`,
    })
    .from(practiceSessions)
    .where(inArray(practiceSessions.studentId, studentIds))
    .groupBy(practiceSessions.studentId)
    .orderBy(desc(sql`MAX(${practiceSessions.startedAt})`))

  return rows.map((r) => ({
    studentId: r.studentId,
    studentName: null, // 由调用方填充
    totalSessions: Number(r.totalSessions),
    completedSessions: Number(r.completedSessions),
    totalQuestionsAnswered: Number(r.totalQuestionsAnswered),
    totalCorrect: Number(r.totalCorrect),
    accuracy: Number(r.totalQuestionsAnswered) > 0
      ? Number(r.totalCorrect) / Number(r.totalQuestionsAnswered)
      : 0,
    lastPracticeAt: r.lastPracticeAt,
  }))
})

/**
 * 获取年级专项练习统计。
 *
 * 使用单条 SQL 同时计算汇总统计与活跃学生数（COUNT(DISTINCT)），
 * 避免 N+1 查询。
 *
 * @param gradeId 年级 ID
 */
export const getGradePracticeStats = cache(async (
  gradeId: string,
): Promise<{
  totalSessions: number
  completedSessions: number
  totalQuestionsAnswered: number
  totalCorrect: number
  averageAccuracy: number
  activeStudents: number
} | null> => {
  const studentIds = await getUserIdsByGradeId(gradeId)
  if (studentIds.length === 0) return null

  const rows = await db
    .select({
      totalSessions: count(),
      completedSessions: count(sql`CASE WHEN ${practiceSessions.status} = 'completed' THEN 1 END`),
      totalQuestionsAnswered: sql<number>`COALESCE(SUM(${practiceSessions.answeredQuestions}), 0)`,
      totalCorrect: sql<number>`COALESCE(SUM(${practiceSessions.correctCount}), 0)`,
      activeStudents: sql<number>`COUNT(DISTINCT ${practiceSessions.studentId})`,
    })
    .from(practiceSessions)
    .where(inArray(practiceSessions.studentId, studentIds))

  const row = rows[0]
  if (!row) return null

  const totalQuestionsAnswered = Number(row.totalQuestionsAnswered)
  const totalCorrect = Number(row.totalCorrect)

  return {
    totalSessions: Number(row.totalSessions),
    completedSessions: Number(row.completedSessions),
    totalQuestionsAnswered,
    totalCorrect,
    averageAccuracy: totalQuestionsAnswered > 0 ? totalCorrect / totalQuestionsAnswered : 0,
    activeStudents: Number(row.activeStudents),
  }
})

/**
 * 获取按练习类型分组的统计（班级或年级维度）。
 *
 * @param studentIds 学生 ID 列表
 */
export const getPracticeTypeBreakdown = cache(async (
  studentIds: string[],
): Promise<PracticeTypeBreakdown[]> => {
  if (studentIds.length === 0) return []

  const rows = await db
    .select({
      practiceType: practiceSessions.practiceType,
      sessionCount: count(),
      totalQuestions: sql<number>`COALESCE(SUM(${practiceSessions.totalQuestions}), 0)`,
      correctCount: sql<number>`COALESCE(SUM(${practiceSessions.correctCount}), 0)`,
    })
    .from(practiceSessions)
    .where(inArray(practiceSessions.studentId, studentIds))
    .groupBy(practiceSessions.practiceType)

  return rows.map((r) => ({
    practiceType: r.practiceType,
    sessionCount: Number(r.sessionCount),
    totalQuestions: Number(r.totalQuestions),
    correctCount: Number(r.correctCount),
    accuracy: Number(r.totalQuestions) > 0
      ? Number(r.correctCount) / Number(r.totalQuestions)
      : 0,
  }))
})

/**
 * 获取班级中未参与专项练习的学生列表。
 *
 * 用于教师识别"从未使用专项练习功能"的学生，
 * 这些学生可能缺乏自主学习意识，需要教师引导。
 *
 * @param classId 班级 ID
 */
export const getStudentsWithoutPractice = cache(async (
  classId: string,
): Promise<string[]> => {
  const studentIds = await getActiveStudentIdsByClassId(classId)
  if (studentIds.length === 0) return []

  // 查询有练习记录的学生
  const activeRows = await db
    .select({ studentId: practiceSessions.studentId })
    .from(practiceSessions)
    .where(inArray(practiceSessions.studentId, studentIds))
    .groupBy(practiceSessions.studentId)

  const activeSet = new Set(activeRows.map((r) => r.studentId))

  // 返回没有练习记录的学生
  return studentIds.filter((id) => !activeSet.has(id))
})

// ---------------------------------------------------------------------------
// 教师视图：所教班级练习概览
// ---------------------------------------------------------------------------

/** 教师所教班级的练习概览（每个班级一行） */
export interface TeacherClassPracticeOverview {
  classId: string
  className: string
  totalSessions: number
  completedSessions: number
  totalQuestionsAnswered: number
  totalCorrect: number
  averageAccuracy: number
  activeStudents: number
  /** 该班级学生总数 */
  totalStudents: number
  /** 参与率 0-1 */
  participationRate: number
}

/**
 * 获取教师所教所有班级的专项练习概览。
 *
 * 用于教师端分析页面顶部展示每个班级的练习情况。
 *
 * N+1 优化：
 * - 批量获取所有班级名称（1 条 SQL 替代 N 条）
 * - 每个班级仅 1 条 SQL 同时计算汇总统计与活跃学生数（合并原先 2 条 SQL）
 *
 * @param classIds 教师/年级主任可访问的班级 ID 列表
 */
export const getTeacherClassPracticeOverviews = cache(async (
  classIds: string[],
): Promise<TeacherClassPracticeOverview[]> => {
  if (classIds.length === 0) return []

  // 批量获取所有班级名称（1 条 SQL）
  const classNameMap = await getClassNamesByIds(classIds)

  // 并行获取每个班级的学生 ID 列表
  const studentIdsPerClass = await Promise.all(
    classIds.map(async (classId) => ({
      classId,
      studentIds: await getActiveStudentIdsByClassId(classId),
    })),
  )

  // 并行获取每个班级的练习统计（单条 SQL 同时计算汇总 + 活跃学生数）
  const statsPerClass = await Promise.all(
    studentIdsPerClass.map(async ({ classId, studentIds }) => {
      const totalStudents = studentIds.length
      if (totalStudents === 0) {
        return {
          classId,
          totalStudents: 0,
          totalSessions: 0,
          completedSessions: 0,
          totalQuestionsAnswered: 0,
          totalCorrect: 0,
          activeStudents: 0,
        }
      }

      const rows = await db
        .select({
          totalSessions: count(),
          completedSessions: count(sql`CASE WHEN ${practiceSessions.status} = 'completed' THEN 1 END`),
          totalQuestionsAnswered: sql<number>`COALESCE(SUM(${practiceSessions.answeredQuestions}), 0)`,
          totalCorrect: sql<number>`COALESCE(SUM(${practiceSessions.correctCount}), 0)`,
          activeStudents: sql<number>`COUNT(DISTINCT ${practiceSessions.studentId})`,
        })
        .from(practiceSessions)
        .where(inArray(practiceSessions.studentId, studentIds))

      const row = rows[0]
      return {
        classId,
        totalStudents,
        totalSessions: Number(row?.totalSessions ?? 0),
        completedSessions: Number(row?.completedSessions ?? 0),
        totalQuestionsAnswered: Number(row?.totalQuestionsAnswered ?? 0),
        totalCorrect: Number(row?.totalCorrect ?? 0),
        activeStudents: Number(row?.activeStudents ?? 0),
      }
    }),
  )

  return statsPerClass.map((s) => {
    const totalQuestionsAnswered = s.totalQuestionsAnswered
    const totalCorrect = s.totalCorrect
    const activeStudents = s.activeStudents
    return {
      classId: s.classId,
      className: classNameMap.get(s.classId) ?? "",
      totalSessions: s.totalSessions,
      completedSessions: s.completedSessions,
      totalQuestionsAnswered,
      totalCorrect,
      averageAccuracy: totalQuestionsAnswered > 0 ? totalCorrect / totalQuestionsAnswered : 0,
      activeStudents,
      totalStudents: s.totalStudents,
      participationRate: s.totalStudents > 0 ? activeStudents / s.totalStudents : 0,
    }
  })
})

// ---------------------------------------------------------------------------
// 班级知识点薄弱度（基于练习答题数据）
// ---------------------------------------------------------------------------

/** 班级知识点薄弱度 */
export interface ClassKnowledgePointWeakness {
  knowledgePointId: string
  knowledgePointName: string
  /** 该知识点总答题数 */
  totalAnswers: number
  /** 该知识点答错数 */
  wrongAnswers: number
  /** 错误率 0-1 */
  errorRate: number
}

/**
 * 获取班级在专项练习中暴露的知识点薄弱度。
 *
 * 通过分析 practiceAnswers 表中 isCorrect = false 的记录，
 * 关联题目到知识点，统计每个知识点的错误率。
 *
 * @param classId 班级 ID
 * @param limit 返回条数（默认 10）
 */
export const getClassKnowledgePointWeakness = cache(async (
  classId: string,
  limit = 10,
): Promise<ClassKnowledgePointWeakness[]> => {
  const studentIds = await getActiveStudentIdsByClassId(classId)
  if (studentIds.length === 0) return []

  // 查询该班级学生在练习中的答题记录（联表题目→知识点）
  const rows = await db
    .select({
      knowledgePointId: knowledgePoints.id,
      knowledgePointName: knowledgePoints.name,
      totalAnswers: count(),
      wrongAnswers: count(sql`CASE WHEN ${practiceAnswers.isCorrect} = false THEN 1 END`),
    })
    .from(practiceAnswers)
    .innerJoin(questions, eq(questions.id, practiceAnswers.questionId))
    .innerJoin(questionsToKnowledgePoints, eq(questionsToKnowledgePoints.questionId, questions.id))
    .innerJoin(knowledgePoints, eq(knowledgePoints.id, questionsToKnowledgePoints.knowledgePointId))
    .where(
      and(
        inArray(practiceAnswers.studentId, studentIds),
        eq(practiceAnswers.status, "answered"),
      ),
    )
    .groupBy(knowledgePoints.id, knowledgePoints.name)
    .orderBy(desc(count()))
    .limit(limit)

  return rows.map((r) => {
    const totalAnswers = Number(r.totalAnswers)
    const wrongAnswers = Number(r.wrongAnswers)
    return {
      knowledgePointId: r.knowledgePointId,
      knowledgePointName: r.knowledgePointName,
      totalAnswers,
      wrongAnswers,
      errorRate: totalAnswers > 0 ? wrongAnswers / totalAnswers : 0,
    }
  })
})

// ---------------------------------------------------------------------------
// 年级视图：各班级练习对比
// ---------------------------------------------------------------------------

/** 年级各班级练习对比 */
export interface GradeClassPracticeComparison {
  classId: string
  className: string
  totalSessions: number
  completedSessions: number
  totalQuestionsAnswered: number
  totalCorrect: number
  averageAccuracy: number
  activeStudents: number
  totalStudents: number
  participationRate: number
}

/**
 * 获取年级各班级专项练习对比数据。
 *
 * N+1 优化：
 * - 班级列表已含名称，无需额外查询
 * - 每个班级仅 1 条 SQL 同时计算汇总统计与活跃学生数（合并原先 2 条 SQL）
 *
 * @param gradeId 年级 ID
 */
export const getGradeClassPracticeComparison = cache(async (
  gradeId: string,
): Promise<GradeClassPracticeComparison[]> => {
  const classList = await getClassesByGradeId(gradeId)
  if (classList.length === 0) return []

  // 并行获取每个班级的学生 ID 列表
  const studentIdsPerClass = await Promise.all(
    classList.map(async (cls) => ({
      cls,
      studentIds: await getActiveStudentIdsByClassId(cls.id),
    })),
  )

  // 并行获取每个班级的练习统计（单条 SQL 同时计算汇总 + 活跃学生数）
  const statsPerClass = await Promise.all(
    studentIdsPerClass.map(async ({ cls, studentIds }) => {
      const totalStudents = studentIds.length
      if (totalStudents === 0) {
        return {
          cls,
          totalStudents: 0,
          totalSessions: 0,
          completedSessions: 0,
          totalQuestionsAnswered: 0,
          totalCorrect: 0,
          activeStudents: 0,
        }
      }

      const rows = await db
        .select({
          totalSessions: count(),
          completedSessions: count(sql`CASE WHEN ${practiceSessions.status} = 'completed' THEN 1 END`),
          totalQuestionsAnswered: sql<number>`COALESCE(SUM(${practiceSessions.answeredQuestions}), 0)`,
          totalCorrect: sql<number>`COALESCE(SUM(${practiceSessions.correctCount}), 0)`,
          activeStudents: sql<number>`COUNT(DISTINCT ${practiceSessions.studentId})`,
        })
        .from(practiceSessions)
        .where(inArray(practiceSessions.studentId, studentIds))

      const row = rows[0]
      return {
        cls,
        totalStudents,
        totalSessions: Number(row?.totalSessions ?? 0),
        completedSessions: Number(row?.completedSessions ?? 0),
        totalQuestionsAnswered: Number(row?.totalQuestionsAnswered ?? 0),
        totalCorrect: Number(row?.totalCorrect ?? 0),
        activeStudents: Number(row?.activeStudents ?? 0),
      }
    }),
  )

  const results = statsPerClass.map((s) => {
    const totalQuestionsAnswered = s.totalQuestionsAnswered
    const totalCorrect = s.totalCorrect
    const activeStudents = s.activeStudents
    return {
      classId: s.cls.id,
      className: s.cls.name,
      totalSessions: s.totalSessions,
      completedSessions: s.completedSessions,
      totalQuestionsAnswered,
      totalCorrect,
      averageAccuracy: totalQuestionsAnswered > 0 ? totalCorrect / totalQuestionsAnswered : 0,
      activeStudents,
      totalStudents: s.totalStudents,
      participationRate: s.totalStudents > 0 ? activeStudents / s.totalStudents : 0,
    }
  })

  // 按参与率降序排列
  return results.sort((a, b) => b.participationRate - a.participationRate)
})

// ---------------------------------------------------------------------------
// 综合宏观数据分析：跨模块整合（错题 + 掌握度 + 练习）
// ---------------------------------------------------------------------------

/** 班级综合学习画像（整合错题、练习、掌握度） */
export interface ClassLearningProfile {
  classId: string
  className: string
  totalStudents: number
  activeStudents: number
  participationRate: number
  totalSessions: number
  completedSessions: number
  totalQuestionsAnswered: number
  totalCorrect: number
  averageAccuracy: number
  /** 未参与练习的学生 ID 列表 */
  inactiveStudentIds: string[]
  /** 知识点薄弱度 Top N */
  weakKnowledgePoints: ClassKnowledgePointWeakness[]
}

/**
 * 获取班级综合学习画像。
 *
 * 整合专项练习数据、知识点薄弱度、未参与学生识别，
 * 为班主任提供宏观决策依据。
 *
 * @param classId 班级 ID
 * @param weakKpLimit 知识点薄弱度返回条数（默认 5）
 */
export const getClassLearningProfile = cache(async (
  classId: string,
  weakKpLimit = 5,
): Promise<ClassLearningProfile | null> => {
  const [className, studentIds, stats, weakKps, inactiveIds] = await Promise.all([
    getClassNameById(classId),
    getActiveStudentIdsByClassId(classId),
    getClassPracticeStats(classId),
    getClassKnowledgePointWeakness(classId, weakKpLimit),
    getStudentsWithoutPractice(classId),
  ])

  if (studentIds.length === 0) return null

  return {
    classId,
    className: className ?? "",
    totalStudents: studentIds.length,
    activeStudents: stats?.activeStudents ?? 0,
    participationRate: studentIds.length > 0
      ? (stats?.activeStudents ?? 0) / studentIds.length
      : 0,
    totalSessions: stats?.totalSessions ?? 0,
    completedSessions: stats?.completedSessions ?? 0,
    totalQuestionsAnswered: stats?.totalQuestionsAnswered ?? 0,
    totalCorrect: stats?.totalCorrect ?? 0,
    averageAccuracy: stats?.averageAccuracy ?? 0,
    inactiveStudentIds: inactiveIds,
    weakKnowledgePoints: weakKps,
  }
})

/**
 * 批量获取学生姓名映射。
 *
 * 跨模块封装 users/data-access 的 getUserNamesByIds，
 * 返回简化的 Map<studentId, name> 供分析页面使用。
 *
 * @param studentIds 学生 ID 列表
 */
export const getStudentNameMap = cache(async (
  studentIds: string[],
): Promise<Map<string, string>> => {
  if (studentIds.length === 0) return new Map()
  const nameMap = await getUserNamesByIds(studentIds)
  const result = new Map<string, string>()
  for (const [id, info] of nameMap.entries()) {
    result.set(id, info.name ?? "Unknown")
  }
  return result
})

/**
 * 获取年级所有班级的练习统计概览。
 *
 * 用于年级主任宏观数据分析页面，一次性获取年级所有班级的练习数据。
 *
 * @param gradeId 年级 ID
 */
export const getGradeClassOverviews = cache(async (
  gradeId: string,
): Promise<GradeClassPracticeComparison[]> => {
  return getGradeClassPracticeComparison(gradeId)
})

/**
 * 获取年级综合练习统计（聚合所有班级）。
 *
 * @param gradeId 年级 ID
 */
export const getGradePracticeOverview = cache(async (
  gradeId: string,
): Promise<{
  totalClasses: number
  totalStudents: number
  activeStudents: number
  participationRate: number
  totalSessions: number
  completedSessions: number
  totalQuestionsAnswered: number
  totalCorrect: number
  averageAccuracy: number
} | null> => {
  const classComparisons = await getGradeClassPracticeComparison(gradeId)
  if (classComparisons.length === 0) return null

  const totalClasses = classComparisons.length
  const totalStudents = classComparisons.reduce((sum, c) => sum + c.totalStudents, 0)
  const activeStudents = classComparisons.reduce((sum, c) => sum + c.activeStudents, 0)
  const totalSessions = classComparisons.reduce((sum, c) => sum + c.totalSessions, 0)
  const completedSessions = classComparisons.reduce((sum, c) => sum + c.completedSessions, 0)
  const totalQuestionsAnswered = classComparisons.reduce((sum, c) => sum + c.totalQuestionsAnswered, 0)
  const totalCorrect = classComparisons.reduce((sum, c) => sum + c.totalCorrect, 0)

  return {
    totalClasses,
    totalStudents,
    activeStudents,
    participationRate: totalStudents > 0 ? activeStudents / totalStudents : 0,
    totalSessions,
    completedSessions,
    totalQuestionsAnswered,
    totalCorrect,
    averageAccuracy: totalQuestionsAnswered > 0 ? totalCorrect / totalQuestionsAnswered : 0,
  }
})
