/**
 * 仪表盘纯逻辑工具函数（与 UI 分离，便于单测）。
 *
 * 所有函数均为纯函数：相同输入 → 相同输出，无副作用。
 */

import type {
  HomeworkAssignmentListItem,
  HomeworkSubmissionListItem,
  StudentHomeworkAssignmentListItem,
  StudentHomeworkProgressStatus,
  TeacherGradeTrendItem,
} from "@/modules/homework/types"
import type { ClassScheduleItem, TeacherClass } from "@/modules/classes/types"

import type {
  StudentTodayScheduleItem,
  TeacherTodayScheduleItem,
  TeacherDashboardData,
} from "@/modules/dashboard/types"

/** 周一=1 ... 周日=7 */
export type Weekday = 1 | 2 | 3 | 4 | 5 | 6 | 7

/**
 * 将 Date 转换为 1-7 周几表示（周一=1，周日=7）。
 * getDay() 返回 0(周日)-6(周六)，需映射为 1-7。
 */
export function toWeekday(d: Date): Weekday {
  const day = d.getDay()
  if (day < 0 || day > 6) {
    throw new Error(`Invalid day from getDay(): ${day}`)
  }
  const WEEKDAY_MAP: readonly Weekday[] = [7, 1, 2, 3, 4, 5, 6]
  return WEEKDAY_MAP[day]
}

/** 学生作业统计结果 */
export interface StudentAssignmentStats {
  dueSoonCount: number
  overdueCount: number
  gradedCount: number
}

/**
 * 单次遍历统计学生作业状态：即将到期 / 已逾期 / 已批改。
 */
export function countStudentAssignments(
  assignments: readonly StudentHomeworkAssignmentListItem[],
  now: Date,
  dueSoonWindowDays = 7,
): StudentAssignmentStats {
  const in7Days = new Date(now)
  in7Days.setDate(in7Days.getDate() + dueSoonWindowDays)

  let dueSoonCount = 0
  let overdueCount = 0
  let gradedCount = 0

  for (const a of assignments) {
    const status: StudentHomeworkProgressStatus = a.progressStatus
    if (status === "graded") {
      gradedCount++
      continue
    }
    if (!a.dueAt) continue
    const due = new Date(a.dueAt)
    if (Number.isNaN(due.getTime())) continue
    if (due >= now && due <= in7Days) {
      dueSoonCount++
    } else if (due < now) {
      overdueCount++
    }
  }

  return { dueSoonCount, overdueCount, gradedCount }
}

/**
 * 按截止日期升序排序作业，取前 N 条作为「即将到期」列表。
 * 无截止日期的作业排到最后。
 */
export function sortUpcomingAssignments(
  assignments: readonly StudentHomeworkAssignmentListItem[],
  limit = 6,
): StudentHomeworkAssignmentListItem[] {
  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
      const aDue = Number.isNaN(aTime) ? Number.POSITIVE_INFINITY : aTime
      const bDue = Number.isNaN(bTime) ? Number.POSITIVE_INFINITY : bTime
      return aDue - bDue
    })
    .slice(0, limit)
}

/**
 * 从课表中筛选指定周几的课程，按开始时间升序排序。
 *
 * `StudentTodayScheduleItem` 与 `TeacherTodayScheduleItem` 结构完全相同，
 * 返回 `StudentTodayScheduleItem[]` 可通过结构化类型赋值给任一类型变量。
 */
export function filterTodaySchedule(
  schedule: readonly ClassScheduleItem[],
  weekday: Weekday,
  classNameById?: ReadonlyMap<string, string>,
): StudentTodayScheduleItem[] {
  return schedule
    .filter((s) => s.weekday === weekday)
    .sort((a, b) => a.startTime.localeCompare(b.startTime))
    .map((s) => ({
      id: s.id,
      classId: s.classId,
      className: classNameById?.get(s.classId) ?? "Class",
      course: s.course,
      startTime: s.startTime,
      endTime: s.endTime,
      location: s.location ?? null,
    }))
}

/** 教师仪表盘派生指标 */
export interface TeacherDashboardMetrics {
  todayScheduleItems: TeacherTodayScheduleItem[]
  toGradeCount: number
  submissionsToGrade: HomeworkSubmissionListItem[]
  activeAssignmentsCount: number
  averageScore: number
  submissionRate: number
}

/**
 * 计算教师仪表盘派生指标：待批改数、进行中作业数、平均分、提交率等。
 */
export function computeTeacherMetrics(
  classes: readonly TeacherClass[],
  schedule: readonly ClassScheduleItem[],
  assignments: readonly HomeworkAssignmentListItem[],
  submissions: readonly HomeworkSubmissionListItem[],
  gradeTrends: readonly TeacherGradeTrendItem[],
  now: Date,
): TeacherDashboardMetrics {
  const todayWeekday = toWeekday(now)
  const classNameById = new Map(classes.map((c) => [c.id, c.name] as const))

  const todayScheduleItems = filterTodaySchedule(
    schedule,
    todayWeekday,
    classNameById,
  )

  const submittedSubmissions = submissions.filter((s) => Boolean(s.submittedAt))
  const toGradeCount = submittedSubmissions.filter((s) => s.status === "submitted").length

  const submissionsToGrade = submittedSubmissions
    .filter((s) => s.status === "submitted")
    .sort((a, b) => {
      const aTime = a.submittedAt ? new Date(a.submittedAt).getTime() : 0
      const bTime = b.submittedAt ? new Date(b.submittedAt).getTime() : 0
      const aDue = Number.isNaN(aTime) ? 0 : aTime
      const bDue = Number.isNaN(bTime) ? 0 : bTime
      return aDue - bDue
    })
    .slice(0, 6)

  const activeAssignmentsCount = assignments.filter((a) => a.status === "published").length

  const totalTrendScore = gradeTrends.reduce((acc, curr) => acc + curr.averageScore, 0)
  const averageScore = gradeTrends.length > 0 ? totalTrendScore / gradeTrends.length : 0

  const totalSubmissions = gradeTrends.reduce((acc, curr) => acc + curr.submissionCount, 0)
  const totalPotentialSubmissions = gradeTrends.reduce((acc, curr) => acc + curr.totalStudents, 0)
  const submissionRate =
    totalPotentialSubmissions > 0 ? (totalSubmissions / totalPotentialSubmissions) * 100 : 0

  return {
    todayScheduleItems,
    toGradeCount,
    submissionsToGrade,
    activeAssignmentsCount,
    averageScore,
    submissionRate,
  }
}

/**
 * 根据当前小时返回问候语时段 key（morning / afternoon / evening）。
 */
export function getGreetingKey(now: Date): "morning" | "afternoon" | "evening" {
  const hour = now.getHours()
  if (hour < 12) return "morning"
  if (hour < 18) return "afternoon"
  return "evening"
}

/** 重导出 TeacherDashboardData 便于 actions 使用 */
export type { TeacherDashboardData }

// ─── 课表状态计算 ──────────────────────────────────────────

/**
 * 将 "HH:MM" 格式的时间字符串转换为当天的分钟数。
 * 无效输入返回 0。
 */
export function timeToMinutes(t: string): number {
  const [h, m] = t.split(":").map(Number)
  return (h ?? 0) * 60 + (m ?? 0)
}

/** 课表项的实时状态 */
export type ScheduleStatus = "live" | "upcoming" | "past"

/**
 * 根据当前时间判断课程状态：进行中 / 即将开始 / 已结束。
 */
export function getScheduleStatus(
  start: string,
  end: string,
  now: Date,
): ScheduleStatus {
  const currentTime = now.getHours() * 60 + now.getMinutes()
  const startTime = timeToMinutes(start)
  const endTime = timeToMinutes(end)

  if (currentTime >= startTime && currentTime <= endTime) return "live"
  if (currentTime < startTime) return "upcoming"
  return "past"
}

// ─── 作业紧急度计算 ────────────────────────────────────────

/** 作业截止时间的紧急度等级 */
export type DueUrgency = "overdue" | "urgent" | "warning" | "normal" | null

/**
 * 根据截止时间与当前时间的差值计算紧急度。
 * - overdue: 已逾期
 * - urgent: 48 小时内
 * - warning: 120 小时内（5 天）
 * - normal: 5 天以上
 * - null: 无截止时间
 */
export function getDueUrgency(dueAt: string | null, now: Date): DueUrgency {
  if (!dueAt) return null
  const due = new Date(dueAt)
  const diffHours = (due.getTime() - now.getTime()) / (1000 * 60 * 60)

  if (diffHours < 0) return "overdue"
  if (diffHours < 48) return "urgent"
  if (diffHours < 120) return "warning"
  return "normal"
}

// ─── 学生作业操作按钮 ─────────────────────────────────────

/** 作业操作按钮的 i18n 键 */
export type ActionLabelKey = "action.review" | "action.view" | "action.continue" | "action.start"

/**
 * 根据作业进度状态返回操作按钮的 i18n 键。
 */
export function getActionLabelKey(status: string): ActionLabelKey {
  if (status === "graded") return "action.review"
  if (status === "submitted") return "action.view"
  if (status === "in_progress") return "action.continue"
  return "action.start"
}

/** 作业操作按钮的视觉变体 */
export type ActionVariant = "default" | "secondary" | "outline"

/**
 * 根据作业进度状态返回操作按钮的视觉变体。
 */
export function getActionVariant(status: string): ActionVariant {
  if (status === "graded" || status === "submitted") return "outline"
  return "default"
}
