export type AttendanceExperience = 'teacher' | 'admin';
export type SchedulePhase = 'upcoming' | 'ongoing' | 'ended';

import { getRoleDomains } from '../../auth/menu-policy';

export function getAttendanceExperience(
  permissions: readonly string[],
  roles: readonly string[],
): AttendanceExperience {
  const domains = getRoleDomains(roles, permissions);
  if (permissions.includes('attendance:edit') || domains.has('academic') || domains.has('super')) {
    return 'admin';
  }
  return 'teacher';
}

function toMinuteOfDay(time: string): number {
  const [hour = 0, minute = 0] = time.split(':').map(Number);
  return hour * 60 + minute;
}

export function getSchedulePhase(
  startTime: string,
  endTime: string,
  now = new Date(),
): SchedulePhase {
  const current = now.getHours() * 60 + now.getMinutes();
  if (current < toMinuteOfDay(startTime)) return 'upcoming';
  if (current <= toMinuteOfDay(endTime)) return 'ongoing';
  return 'ended';
}

export function canPullAttendance(phase: SchedulePhase): boolean {
  return phase !== 'upcoming';
}

export interface AttendanceSummary {
  total: number;
  present: number;
  late: number;
  absent: number;
  leave: number;
  pending: number;
}

export function summarizeAttendance(records: readonly { status: string }[]): AttendanceSummary {
  const summary: AttendanceSummary = {
    total: records.length,
    present: 0,
    late: 0,
    absent: 0,
    leave: 0,
    pending: 0,
  };
  for (const record of records) {
    if (record.status in summary && record.status !== 'total') {
      summary[record.status as Exclude<keyof AttendanceSummary, 'total'>] += 1;
    }
  }
  return summary;
}

export interface LessonCheckinSummary {
  total: number;
  checkedIn: number;
  notCheckedIn: number;
}

export function summarizeLessonCheckins(
  records: readonly { status: string }[],
): LessonCheckinSummary {
  const checkedIn = records.filter(
    (record) => record.status === 'present' || record.status === 'late',
  ).length;
  return {
    total: records.length,
    checkedIn,
    notCheckedIn: records.length - checkedIn,
  };
}

export type LessonAttendanceFilter = 'all' | 'checked_in' | 'not_checked_in';

export interface LessonAttendanceFilterRecord {
  student: { name: string };
  status: string;
}

export function filterLessonAttendanceRecords<T extends LessonAttendanceFilterRecord>(
  records: readonly T[],
  keyword: string,
  filter: LessonAttendanceFilter,
): T[] {
  const normalizedKeyword = keyword.trim().toLocaleLowerCase('zh-CN');
  return records.filter((record) => {
    const matchesKeyword =
      !normalizedKeyword ||
      record.student.name.toLocaleLowerCase('zh-CN').includes(normalizedKeyword);
    if (!matchesKeyword || filter === 'all') return matchesKeyword;

    const checkedIn = record.status === 'present' || record.status === 'late';
    return filter === 'checked_in' ? checkedIn : !checkedIn;
  });
}

export interface PunchDisplayRecord {
  status: string;
  source?: string;
  punchTime?: string | null;
  punchSource?: string | null;
  punchDeviceName?: string | null;
  punchDeviceId?: string | null;
}

export interface PunchDisplayInfo {
  label: string;
  machine: boolean;
  detail?: string;
  time?: string;
}

export function getPunchDisplayInfo(record: PunchDisplayRecord): PunchDisplayInfo | null {
  if (record.status !== 'present' && record.status !== 'late') return null;
  if (record.source === 'manual') return { label: '老师手动标记', machine: false };

  const source = (record.punchSource || '').trim().toUpperCase();
  const machine = ['ATM', 'ATTENDANCE_MACHINE', 'MACHINE', 'DEVICE'].some(
    (value) => source === value || source.includes(value),
  );
  const label = machine
    ? '考勤机打卡'
    : source === 'USER'
      ? '手机打卡'
      : source.includes('BEACON') || source.includes('BLE')
        ? '蓝牙打卡'
        : source.includes('WIFI')
          ? 'Wi-Fi 打卡'
          : source.includes('APPROVE')
            ? '审批补卡'
            : source
              ? `其他打卡（${record.punchSource}）`
              : '打卡来源未知';
  const device = record.punchDeviceName?.trim();
  const deviceId = record.punchDeviceId?.trim();
  const detail = device
    ? deviceId && deviceId !== device
      ? `${device}（${deviceId}）`
      : device
    : deviceId || undefined;
  return {
    label,
    machine,
    detail,
    time: record.punchTime || undefined,
  };
}
