import type {
  AttendanceWarning,
  AttendanceWarningSeverity,
  AttendanceWarningSummary,
} from "./types"

/**
 * L-3：预警阈值默认值（当班级未配置规则时使用）。
 */
export const DEFAULT_ATTENDANCE_RATE_THRESHOLD = 90
export const DEFAULT_CONSECUTIVE_ABSENCE_THRESHOLD = 3

/**
 * 出勤率预警的严重等级划分：
 * - high：低于阈值 10 个百分点以上
 * - medium：低于阈值 5-10 个百分点
 * - low：低于阈值 5 个百分点以内
 */
const rateSeverity = (current: number, threshold: number): AttendanceWarningSeverity => {
  const diff = threshold - current
  if (diff >= 10) return "high"
  if (diff >= 5) return "medium"
  return "low"
}

/**
 * 连续缺勤预警的严重等级划分：
 * - high：连续缺勤 ≥ 阈值 + 2
 * - medium：连续缺勤 ≥ 阈值 + 1
 * - low：连续缺勤 = 阈值
 */
const absenceSeverity = (current: number, threshold: number): AttendanceWarningSeverity => {
  if (current >= threshold + 2) return "high"
  if (current >= threshold + 1) return "medium"
  return "low"
}

/**
 * 从按日期升序的状态列表中计算最长连续缺勤段。
 * 缺勤定义为 status === "absent"（不含 late/early_leave 等其他异常状态）。
 * 返回 { maxStreak, lastStreakDates }：最长连续段及其日期列表。
 */
export const computeConsecutiveAbsence = (
  records: { date: string; status: string }[]
): { maxStreak: number; lastStreakDates: string[] } => {
  if (records.length === 0) return { maxStreak: 0, lastStreakDates: [] }

  // 按日期升序排序
  const sorted = [...records].sort((a, b) => a.date.localeCompare(b.date))
  let maxStreak = 0
  let currentStreak = 0
  let currentStreakStart = 0
  let lastMaxStart = 0

  for (let i = 0; i < sorted.length; i++) {
    if (sorted[i].status === "absent") {
      if (currentStreak === 0) currentStreakStart = i
      currentStreak += 1
      if (currentStreak > maxStreak) {
        maxStreak = currentStreak
        lastMaxStart = currentStreakStart
      }
    } else {
      currentStreak = 0
    }
  }

  const lastStreakDates = maxStreak > 0
    ? sorted.slice(lastMaxStart, lastMaxStart + maxStreak).map((r) => r.date)
    : []

  return { maxStreak, lastStreakDates }
}

/**
 * L-3：根据学生出勤率统计和阈值生成预警列表（纯函数，便于测试）。
 *
 * @param studentStats 学生列表，每项含 studentId/studentName/total/present 和按日期升序的记录
 * @param attendanceRateThreshold 出勤率阈值（百分比）
 * @param consecutiveAbsenceThreshold 连续缺勤阈值（次）
 */
export const computeAttendanceWarnings = (
  studentStats: {
    studentId: string
    studentName: string
    total: number
    present: number
    records: { date: string; status: string }[]
  }[],
  attendanceRateThreshold: number,
  consecutiveAbsenceThreshold: number
): AttendanceWarning[] => {
  const warnings: AttendanceWarning[] = []

  for (const s of studentStats) {
    // 跳过无记录的学生（避免除零，且无记录不触发预警）
    if (s.total === 0) continue

    const presentRate = Math.round((s.present / s.total) * 10000) / 100

    // 出勤率低于阈值
    if (presentRate < attendanceRateThreshold) {
      warnings.push({
        studentId: s.studentId,
        studentName: s.studentName,
        type: "low_attendance_rate",
        severity: rateSeverity(presentRate, attendanceRateThreshold),
        currentValue: presentRate,
        threshold: attendanceRateThreshold,
        relatedDates: [],
      })
    }

    // 连续缺勤达到阈值
    const { maxStreak, lastStreakDates } = computeConsecutiveAbsence(s.records)
    if (maxStreak >= consecutiveAbsenceThreshold) {
      warnings.push({
        studentId: s.studentId,
        studentName: s.studentName,
        type: "consecutive_absence",
        severity: absenceSeverity(maxStreak, consecutiveAbsenceThreshold),
        currentValue: maxStreak,
        threshold: consecutiveAbsenceThreshold,
        relatedDates: lastStreakDates,
      })
    }
  }

  // 严重等级排序：high → medium → low
  const severityOrder: Record<AttendanceWarningSeverity, number> = {
    high: 0,
    medium: 1,
    low: 2,
  }
  warnings.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity])

  return warnings
}

/**
 * 构造空的预警汇总（当班级无数据或无规则时使用）。
 */
export const createEmptyWarningSummary = (
  classId: string,
  className: string
): AttendanceWarningSummary => ({
  classId,
  className,
  attendanceRateThreshold: DEFAULT_ATTENDANCE_RATE_THRESHOLD,
  consecutiveAbsenceThreshold: DEFAULT_CONSECUTIVE_ABSENCE_THRESHOLD,
  warnings: [],
})
