/**
 * Mock 考勤数据（P7-admin：考勤子模块）
 *
 * 维护者：ai13（teacher-portal）
 *
 * 覆盖：
 * - 5 个班级 × 30 学生 × 30 天 = 4500 条考勤记录（确定性伪随机）
 * - 班级考勤统计（出勤率/迟到率/早退率/请假率）
 * - 30 天每日趋势数据
 * - 学生考勤预警（出勤率 < 90%）
 * - 考勤报告数据（周报/月报）
 */

import type {
  AttendanceRecord,
  AttendanceStatus,
  AttendanceListFilter,
  AttendanceListResult,
  AttendanceSheetItem,
  SaveAttendanceSheetInput,
  SaveAttendanceSheetResult,
  AttendanceStats,
  AttendanceTrendPoint,
  AttendanceClassComparison,
  AttendanceWarning,
  AttendanceReport,
  AttendanceReportType,
  AttendanceReportDetail,
} from "@/lib/graphql-p7-admin";
import { EXTENDED_CLASSES } from "./grades-extended";

/** 5 个班级 ID 列表 */
const CLASS_IDS = EXTENDED_CLASSES.map((c) => c.id);

/** 30 天日期列表（从今天往前回溯 29 天） */
function buildDateRange(days: number): string[] {
  const dates: string[] = [];
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  for (let i = days - 1; i >= 0; i--) {
    const d = new Date(today);
    d.setDate(d.getDate() - i);
    dates.push(formatDate(d));
  }
  return dates;
}

/** 格式化日期 YYYY-MM-DD */
function formatDate(d: Date): string {
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, "0");
  const day = String(d.getDate()).padStart(2, "0");
  return `${y}-${m}-${day}`;
}

/** 30 天日期列表 */
export const ATTENDANCE_DATES = buildDateRange(30);

/** 确定性伪随机 */
function seededRandom(seed: number): number {
  const x = Math.sin(seed) * 10000;
  return x - Math.floor(x);
}

/** 基于字符串生成 seed */
function strToSeed(s: string): number {
  let h = 0;
  for (let i = 0; i < s.length; i++) {
    h = (h * 31 + s.charCodeAt(i)) | 0;
  }
  return Math.abs(h) + 1;
}

/** 生成单生学号 */
function studentNoFor(classIdx: number, studentIdx: number): string {
  return `2026${String(classIdx + 1).padStart(2, "0")}${String(studentIdx).padStart(3, "0")}`;
}

/** 生成单生 ID */
function studentIdFor(classId: string, studentIdx: number): string {
  return `stu-${classId.slice(-4)}-${String(studentIdx).padStart(3, "0")}`;
}

/** 学生姓名（确定性） */
function studentNameFor(studentIdx: number): string {
  return `学生${String(studentIdx).padStart(2, "0")}`;
}

/** 班级出勤率基准（与 grades-extended 对齐） */
const CLASS_PRESENT_RATE_BASE: Record<string, number> = {
  "550e8400-e29b-41d4-a716-446655440010": 95,
  "550e8400-e29b-41d4-a716-446655440011": 92,
  "550e8400-e29b-41d4-a716-446655440012": 90,
  "550e8400-e29b-41d4-a716-446655440013": 93,
  "550e8400-e29b-41d4-a716-446655440014": 96,
};

/** 根据班级 + 学生 + 日期生成确定性考勤状态 */
function pickStatus(
  classId: string,
  studentIdx: number,
  dateStr: string,
): AttendanceStatus {
  const base = CLASS_PRESENT_RATE_BASE[classId] ?? 92;
  const seed = strToSeed(`${classId}-${studentIdx}-${dateStr}`);
  const r = seededRandom(seed);
  // 调整：班级越强，出勤率越高
  const presentThreshold = base / 100;
  const lateThreshold = presentThreshold + 0.03;
  const leaveThreshold = lateThreshold + 0.02;
  const earlyLeaveThreshold = leaveThreshold + 0.015;
  if (r < presentThreshold) return "PRESENT";
  if (r < lateThreshold) return "LATE";
  if (r < leaveThreshold) return "LEAVE";
  if (r < earlyLeaveThreshold) return "EARLY_LEAVE";
  return "ABSENT";
}

/** 生成全量考勤记录（4500 条） */
function generateAllRecords(): AttendanceRecord[] {
  const records: AttendanceRecord[] = [];
  CLASS_IDS.forEach((classId, classIdx) => {
    const cls = EXTENDED_CLASSES[classIdx];
    if (!cls) return;
    for (const date of ATTENDANCE_DATES) {
      // 周末（周六/周日）跳过：基于日期字符串判断
      const dayOfWeek = new Date(date).getDay();
      if (dayOfWeek === 0 || dayOfWeek === 6) continue;
      for (let s = 1; s <= 30; s++) {
        const status = pickStatus(classId, s, date);
        const note =
          status === "ABSENT"
            ? "未到校，需跟进"
            : status === "LEAVE"
              ? "已提交请假条"
              : status === "LATE"
                ? "迟到 5 分钟"
                : null;
        records.push({
          id: `att-${cls.id.slice(-4)}-${date}-${String(s).padStart(3, "0")}`,
          classId,
          className: cls.name,
          studentId: studentIdFor(classId, s),
          studentName: studentNameFor(s),
          studentNo: studentNoFor(classIdx, s),
          date,
          status,
          note,
        });
      }
    }
  });
  return records;
}

/** 全量考勤记录缓存 */
const ALL_RECORDS: AttendanceRecord[] = generateAllRecords();

/** 保存的考勤覆盖（key = `${classId}|${date}|${studentId}`），用于 SaveAttendanceSheet 后即时反映 */
const SAVED_OVERRIDES = new Map<string, AttendanceStatus>();

function makeOverrideKey(
  classId: string,
  date: string,
  studentId: string,
): string {
  return `${classId}|${date}|${studentId}`;
}

/** 应用覆盖后的状态读取 */
function resolveStatus(
  classId: string,
  date: string,
  studentId: string,
  fallback: AttendanceStatus,
): AttendanceStatus {
  const override = SAVED_OVERRIDES.get(
    makeOverrideKey(classId, date, studentId),
  );
  return override ?? fallback;
}

/** 考勤列表查询（按筛选 + 分页） */
export function queryAttendanceList(
  filter: AttendanceListFilter,
): AttendanceListResult {
  const { classId, startDate, endDate, statuses, page, pageSize } = filter;
  const safePage = page ?? 1;
  const safePageSize = pageSize ?? 30;

  const statusSet = statuses && statuses.length > 0 ? new Set(statuses) : null;

  const filtered = ALL_RECORDS.filter((r) => {
    if (classId && r.classId !== classId) return false;
    if (startDate && r.date < startDate) return false;
    if (endDate && r.date > endDate) return false;
    if (statusSet && !statusSet.has(r.status)) return false;
    return true;
  });

  const total = filtered.length;
  const totalPages = Math.max(1, Math.ceil(total / safePageSize));
  const currentPage = Math.min(Math.max(1, safePage), totalPages);
  const start = (currentPage - 1) * safePageSize;
  const items = filtered.slice(start, start + safePageSize);

  return {
    items,
    total,
    page: currentPage,
    pageSize: safePageSize,
    totalPages,
  };
}

/** 考勤录入查询（按 classId + date 拉取学生 + 当天状态） */
export function queryAttendanceSheet(
  classId: string,
  date: string,
): AttendanceSheetItem[] {
  const cls = EXTENDED_CLASSES.find((c) => c.id === classId);
  if (!cls) return [];
  const classIdx = EXTENDED_CLASSES.indexOf(cls);
  const items: AttendanceSheetItem[] = [];
  for (let s = 1; s <= 30; s++) {
    const studentId = studentIdFor(classId, s);
    const baseStatus = pickStatus(classId, s, date);
    const status = resolveStatus(classId, date, studentId, baseStatus);
    items.push({
      studentId,
      studentName: studentNameFor(s),
      studentNo: studentNoFor(classIdx, s),
      date,
      status,
      note:
        status === "ABSENT"
          ? "未到校，需跟进"
          : status === "LEAVE"
            ? "已提交请假条"
            : null,
    });
  }
  return items;
}

/** 批量保存考勤录入 */
export function saveAttendanceSheet(
  input: SaveAttendanceSheetInput,
): SaveAttendanceSheetResult {
  for (const rec of input.records) {
    SAVED_OVERRIDES.set(
      makeOverrideKey(input.classId, input.date, rec.studentId),
      rec.status,
    );
  }
  return {
    classId: input.classId,
    date: input.date,
    savedCount: input.records.length,
    savedAt: new Date().toISOString(),
  };
}

/** 计算班级考勤统计 */
export function queryAttendanceStats(
  classId: string,
  startDate: string,
  endDate: string,
): AttendanceStats {
  const cls = EXTENDED_CLASSES.find((c) => c.id === classId);
  const className = cls?.name ?? "未知班级";
  const classRecords = ALL_RECORDS.filter((r) => {
    if (r.classId !== classId) return false;
    if (r.date < startDate || r.date > endDate) return false;
    return true;
  });

  const total = classRecords.length;
  const counts = { present: 0, absent: 0, late: 0, earlyLeave: 0, leave: 0 };
  for (const r of classRecords) {
    if (r.status === "PRESENT") counts.present++;
    else if (r.status === "ABSENT") counts.absent++;
    else if (r.status === "LATE") counts.late++;
    else if (r.status === "EARLY_LEAVE") counts.earlyLeave++;
    else if (r.status === "LEAVE") counts.leave++;
  }

  const safeDiv = (n: number): number =>
    total === 0 ? 0 : Math.round((n / total) * 1000) / 10;

  const trend = buildTrend(classId, startDate, endDate);
  const warningCount = computeWarnings(classId, startDate, endDate).length;

  return {
    classId,
    className,
    startDate,
    endDate,
    totalRecords: total,
    presentCount: counts.present,
    absentCount: counts.absent,
    lateCount: counts.late,
    earlyLeaveCount: counts.earlyLeave,
    leaveCount: counts.leave,
    presentRate: safeDiv(counts.present),
    lateRate: safeDiv(counts.late),
    earlyLeaveRate: safeDiv(counts.earlyLeave),
    leaveRate: safeDiv(counts.leave),
    warningCount,
    trend,
  };
}

/** 构建趋势（按日聚合） */
function buildTrend(
  classId: string,
  startDate: string,
  endDate: string,
): AttendanceTrendPoint[] {
  const dates = ATTENDANCE_DATES.filter((d) => d >= startDate && d <= endDate);
  return dates.map((date) => {
    const dayRecords = ALL_RECORDS.filter(
      (r) => r.classId === classId && r.date === date,
    );
    const total = dayRecords.length;
    const safeDiv = (n: number): number =>
      total === 0 ? 0 : Math.round((n / total) * 1000) / 10;
    const present = dayRecords.filter((r) => r.status === "PRESENT").length;
    const late = dayRecords.filter((r) => r.status === "LATE").length;
    const absent = dayRecords.filter((r) => r.status === "ABSENT").length;
    return {
      date,
      presentRate: safeDiv(present),
      lateRate: safeDiv(late),
      absentRate: safeDiv(absent),
    };
  });
}

/** 班级考勤对比 */
export function queryAttendanceClassComparison(
  startDate: string,
  endDate: string,
): AttendanceClassComparison[] {
  return CLASS_IDS.map((classId) => {
    const stats = queryAttendanceStats(classId, startDate, endDate);
    const cls = EXTENDED_CLASSES.find((c) => c.id === classId);
    return {
      classId,
      className: cls?.name ?? "未知班级",
      presentRate: stats.presentRate,
      lateRate: stats.lateRate,
      absentRate: Math.round(
        (stats.absentCount / Math.max(1, stats.totalRecords)) * 1000,
      ) / 10,
    };
  });
}

/** 学生考勤预警（出勤率 < 90%） */
function computeWarnings(
  classId: string,
  startDate: string,
  endDate: string,
): AttendanceWarning[] {
  const cls = EXTENDED_CLASSES.find((c) => c.id === classId);
  if (!cls) return [];
  const classIdx = EXTENDED_CLASSES.indexOf(cls);
  const warnings: AttendanceWarning[] = [];
  for (let s = 1; s <= 30; s++) {
    const studentId = studentIdFor(classId, s);
    const studentRecords = ALL_RECORDS.filter((r) => {
      if (r.classId !== classId) return false;
      if (r.studentId !== studentId) return false;
      if (r.date < startDate || r.date > endDate) return false;
      return true;
    });
    const total = studentRecords.length;
    if (total === 0) continue;
    const present = studentRecords.filter((r) => r.status === "PRESENT").length;
    const rate = Math.round((present / total) * 1000) / 10;
    if (rate < 90) {
      warnings.push({
        studentId,
        studentName: studentNameFor(s),
        studentNo: studentNoFor(classIdx, s),
        className: cls.name,
        presentRate: rate,
        absentCount: studentRecords.filter((r) => r.status === "ABSENT").length,
        lateCount: studentRecords.filter((r) => r.status === "LATE").length,
      });
    }
  }
  // 按出勤率升序
  warnings.sort((a, b) => a.presentRate - b.presentRate);
  return warnings;
}

/** 学生考勤预警查询入口 */
export function queryAttendanceWarnings(
  classId: string,
  startDate: string,
  endDate: string,
): AttendanceWarning[] {
  return computeWarnings(classId, startDate, endDate);
}

/** 考勤报告查询 */
export function queryAttendanceReport(
  classId: string,
  reportType: AttendanceReportType,
  startDate: string,
  endDate: string,
): AttendanceReport {
  const cls = EXTENDED_CLASSES.find((c) => c.id === classId);
  const className = cls?.name ?? "未知班级";
  const stats = queryAttendanceStats(classId, startDate, endDate);
  const details = buildReportDetails(classId, startDate, endDate);
  return {
    classId,
    className,
    reportType,
    startDate,
    endDate,
    generatedAt: new Date().toISOString(),
    summary: {
      totalRecords: stats.totalRecords,
      presentRate: stats.presentRate,
      lateRate: stats.lateRate,
      earlyLeaveRate: stats.earlyLeaveRate,
      leaveRate: stats.leaveRate,
      warningCount: stats.warningCount,
    },
    details,
  };
}

/** 构建报告明细（按学生聚合） */
function buildReportDetails(
  classId: string,
  startDate: string,
  endDate: string,
): AttendanceReportDetail[] {
  const cls = EXTENDED_CLASSES.find((c) => c.id === classId);
  if (!cls) return [];
  const classIdx = EXTENDED_CLASSES.indexOf(cls);
  const details: AttendanceReportDetail[] = [];
  for (let s = 1; s <= 30; s++) {
    const studentId = studentIdFor(classId, s);
    const studentRecords = ALL_RECORDS.filter((r) => {
      if (r.classId !== classId) return false;
      if (r.studentId !== studentId) return false;
      if (r.date < startDate || r.date > endDate) return false;
      return true;
    });
    const total = studentRecords.length;
    if (total === 0) continue;
    const present = studentRecords.filter((r) => r.status === "PRESENT").length;
    const absent = studentRecords.filter((r) => r.status === "ABSENT").length;
    const late = studentRecords.filter((r) => r.status === "LATE").length;
    const earlyLeave = studentRecords.filter(
      (r) => r.status === "EARLY_LEAVE",
    ).length;
    const leave = studentRecords.filter((r) => r.status === "LEAVE").length;
    details.push({
      studentId,
      studentName: studentNameFor(s),
      studentNo: studentNoFor(classIdx, s),
      presentCount: present,
      absentCount: absent,
      lateCount: late,
      earlyLeaveCount: earlyLeave,
      leaveCount: leave,
      presentRate: Math.round((present / total) * 1000) / 10,
    });
  }
  // 按出勤率降序
  details.sort((a, b) => b.presentRate - a.presentRate);
  return details;
}

/** 考勤列表分页类型重导出（供 handlers 使用） */
export type { AttendanceListResult };

/** 默认日期范围（近 7 天） */
export function defaultDateRange(): { startDate: string; endDate: string } {
  const dates = ATTENDANCE_DATES;
  const end = dates[dates.length - 1] ?? formatDate(new Date());
  const startIdx = Math.max(0, dates.length - 7);
  const start = dates[startIdx] ?? end;
  return { startDate: start, endDate: end };
}

/** 近 30 天日期范围 */
export function fullDateRange(): { startDate: string; endDate: string } {
  const dates = ATTENDANCE_DATES;
  return {
    startDate: dates[0] ?? formatDate(new Date()),
    endDate: dates[dates.length - 1] ?? formatDate(new Date()),
  };
}
