import type { StudentHomeworkAssignmentListItem } from "@/modules/homework/types"

/**
 * 学生概览纯数据计算
 *
 * 将数据获取与计算逻辑从页面组件中抽出，便于单元测试。
 * 输入为已获取的原始数据，输出为 UI 直接消费的视图模型。
 */

export interface StudentScheduleItem {
  id: string
  classId: string
  className: string
  course: string
  startTime: string
  endTime: string
  location: string | null
}

export interface StudentOverviewData<TGrades = unknown> {
  enrolledClassCount: number
  dueSoonCount: number
  overdueCount: number
  gradedCount: number
  todayScheduleItems: StudentScheduleItem[]
  upcomingAssignments: StudentHomeworkAssignmentListItem[]
  grades: TGrades
}

const WEEKDAY_MAP = [7, 1, 2, 3, 4, 5, 6] as const
type Weekday = 1 | 2 | 3 | 4 | 5 | 6 | 7

export function toWeekday(d: Date): Weekday {
  const day = d.getDay()
  const result = WEEKDAY_MAP[day]
  if (result < 1 || result > 7) throw new Error("Invalid weekday")
  return result
}

interface RawScheduleItem {
  id: string
  classId: string
  className: string
  course: string
  startTime: string
  endTime: string
  location?: string | null
  weekday: number
}

interface RawAssignment {
  id: string
  dueAt: string | null
  progressStatus: string
}

/**
 * 从原始作业列表计算学生概览统计
 */
export function computeStudentStats(
  assignments: ReadonlyArray<RawAssignment>,
  now: Date = new Date()
): { dueSoonCount: number; overdueCount: number; gradedCount: number } {
  const in7Days = new Date(now)
  in7Days.setDate(in7Days.getDate() + 7)

  const dueSoonCount = assignments.filter((a) => {
    if (!a.dueAt) return false
    const due = new Date(a.dueAt)
    return due >= now && due <= in7Days && a.progressStatus !== "graded"
  }).length

  const overdueCount = assignments.filter((a) => {
    if (!a.dueAt) return false
    const due = new Date(a.dueAt)
    return due < now && a.progressStatus !== "graded"
  }).length

  const gradedCount = assignments.filter((a) => a.progressStatus === "graded").length

  return { dueSoonCount, overdueCount, gradedCount }
}

/**
 * 排序并截取即将到期的作业列表
 */
export function sortUpcomingAssignments<T extends RawAssignment>(
  assignments: ReadonlyArray<T>,
  limit: number = 8
): T[] {
  return [...assignments]
    .sort((a, b) => {
      const aTime = a.dueAt ? new Date(a.dueAt).getTime() : Number.POSITIVE_INFINITY
      const bTime = b.dueAt ? new Date(b.dueAt).getTime() : Number.POSITIVE_INFINITY
      if (aTime !== bTime) return aTime - bTime
      return a.id.localeCompare(b.id)
    })
    .slice(0, limit)
}

/**
 * 过滤今日课表
 */
export function filterTodaySchedule<T extends RawScheduleItem>(
  schedule: ReadonlyArray<T>,
  now: Date = new Date()
): StudentScheduleItem[] {
  const todayWeekday = toWeekday(now)
  return schedule
    .filter((s) => s.weekday === todayWeekday)
    .map((s) => ({
      id: s.id,
      classId: s.classId,
      className: s.className,
      course: s.course,
      startTime: s.startTime,
      endTime: s.endTime,
      location: s.location ?? null,
    }))
}

/**
 * 组装完整的学生概览视图模型
 */
export function buildStudentOverviewData<TGrades>(
  params: {
    classes: ReadonlyArray<unknown>
    schedule: ReadonlyArray<RawScheduleItem>
    assignments: ReadonlyArray<StudentHomeworkAssignmentListItem>
    grades: TGrades
    now?: Date
  }
): StudentOverviewData<TGrades> {
  const { classes, schedule, assignments, grades, now = new Date() } = params
  const stats = computeStudentStats(assignments, now)
  const upcomingAssignments = sortUpcomingAssignments(assignments)
  const todayScheduleItems = filterTodaySchedule(schedule, now)

  return {
    enrolledClassCount: classes.length,
    dueSoonCount: stats.dueSoonCount,
    overdueCount: stats.overdueCount,
    gradedCount: stats.gradedCount,
    todayScheduleItems,
    upcomingAssignments,
    grades,
  }
}
