const API_BASE = 'http://127.0.0.1:8080/api';

function getToken(): string | null {
  return localStorage.getItem('sc_staff_token');
}

export async function staffFetch(path: string, init: RequestInit = {}): Promise<Response> {
  const headers = new Headers(init.headers);
  const token = getToken();
  if (token) headers.set('Authorization', `Bearer ${token}`);
  if (init.body && !headers.has('Content-Type')) {
    headers.set('Content-Type', 'application/json');
  }
  return fetch(`${API_BASE}${path}`, { ...init, headers });
}

async function parseError(res: Response, fallback: string): Promise<never> {
  const errData = await res.json().catch(() => ({}));
  const msg = (errData as { error?: string }).error;
  if (msg) throw new Error(msg);
  if (res.status === 413) throw new Error('File quá lớn (tối đa 100MB)');
  throw new Error(`${fallback} (HTTP ${res.status})`);
}

export interface StaffUser {
  id: number;
  email: string;
  fullName: string;
  mustChangePassword: boolean;
}

export const apiAuth = {
  provision: async (email: string): Promise<{ ok: boolean; message: string }> => {
    const res = await fetch(`${API_BASE}/auth/provision`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email }),
    });
    if (!res.ok) await parseError(res, 'Provision failed');
    return res.json();
  },
  login: async (email: string, password: string): Promise<{ token: string; staff: StaffUser; mustChangePassword: boolean }> => {
    const res = await fetch(`${API_BASE}/auth/login`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email, password }),
    });
    if (!res.ok) await parseError(res, 'Đăng nhập thất bại');
    return res.json();
  },
  me: async (): Promise<{ staff: StaffUser }> => {
    const res = await staffFetch('/auth/me');
    if (!res.ok) await parseError(res, 'Unauthorized');
    return res.json();
  },
  changePassword: async (oldPassword: string, newPassword: string): Promise<{ ok: boolean; token: string; staff: StaffUser }> => {
    const res = await staffFetch('/auth/change-password', {
      method: 'POST',
      body: JSON.stringify({ oldPassword, newPassword }),
    });
    if (!res.ok) await parseError(res, 'Đổi mật khẩu thất bại');
    return res.json();
  },
  forgotPassword: async (email: string): Promise<{ ok: boolean; message: string }> => {
    const res = await fetch(`${API_BASE}/auth/forgot-password`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email }),
    });
    if (!res.ok) await parseError(res, 'Gửi mail thất bại');
    return res.json();
  },
  resetPassword: async (token: string, newPassword: string): Promise<{ ok: boolean; message: string }> => {
    const res = await fetch(`${API_BASE}/auth/reset-password`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ token, newPassword }),
    });
    if (!res.ok) await parseError(res, 'Đặt lại mật khẩu thất bại');
    return res.json();
  },
};

export interface EmailDomainItem {
  id: number;
  domain: string;
  isActive: boolean;
}

export const apiAdmin = {
  listEmailDomains: async (): Promise<{ data: EmailDomainItem[] }> => {
    const res = await staffFetch('/admin/email-domains');
    if (!res.ok) await parseError(res, 'Failed');
    return res.json();
  },
  addEmailDomain: async (domain: string) => {
    const res = await staffFetch('/admin/email-domains', { method: 'POST', body: JSON.stringify({ domain }) });
    if (!res.ok) await parseError(res, 'Failed');
    return res.json();
  },
  deleteEmailDomain: async (id: number) => {
    const res = await staffFetch(`/admin/email-domains/${id}`, { method: 'DELETE' });
    if (!res.ok) await parseError(res, 'Failed');
    return res.json();
  },
};

export interface ChatStudent {
  studentRkId: number;
  fullName: string;
  studentCode: string;
  email: string;
  online: boolean;
}

export interface ChatMessage {
  id: number;
  staffId: number;
  targetStaffId?: number;
  studentRkId: number;
  senderRole: 'staff' | 'student';
  body: string;
  createdAt: string;
  staffName?: string;
}

export interface ChatConversation {
  studentRkId: number;
  fullName: string;
  studentCode: string;
  lastMessage: string;
  lastAt: string;
  unread: number;
}

export const apiChat = {
  listConversations: async (): Promise<{ data: ChatConversation[] }> => {
    const res = await staffFetch('/chat/conversations');
    if (!res.ok) await parseError(res, 'Failed');
    return res.json();
  },
  searchStudents: async (q = ''): Promise<{ data: ChatStudent[] }> => {
    const params = q ? `?q=${encodeURIComponent(q)}` : '';
    const res = await staffFetch(`/chat/students${params}`);
    if (!res.ok) await parseError(res, 'Failed');
    return res.json();
  },
  listMessages: async (studentRkId: number): Promise<{ data: ChatMessage[] }> => {
    const res = await staffFetch(`/chat/messages/${studentRkId}`);
    if (!res.ok) await parseError(res, 'Failed');
    return res.json();
  },
  sendMessage: async (studentRkId: number, body: string): Promise<{ ok: boolean; data: ChatMessage }> => {
    const res = await staffFetch('/chat/messages', {
      method: 'POST',
      body: JSON.stringify({ studentRkId, body }),
    });
    if (!res.ok) await parseError(res, 'Failed');
    return res.json();
  },
};

export interface ClassItem {
  rkId: number;
  name: string;
  classCode: string;
  type: string;
  studentCount: number;
  specializeRkId?: number;
  specializeName?: string;
  systemRkId?: number;
  systemCode?: string;
  systemName?: string;
  isStudying: boolean;
  courses: { courseRkId: number; courseName: string }[];
}

export interface StudentItem {
  id: number;
  rkId: number;
  studentCode: string;
  fullName: string;
  phone?: string;
  email: string;
  dateOfBirth?: string;
  gender?: number;
  status?: string;
  location?: string;
  systemId?: number;
  systemName?: string;
  avatar?: string;
}

export interface StatsResponse {
  totalClasses: number;
  activeClasses: number;
  totalStudents: number;
}

export interface PaginatedResponse<T> {
  data: T[];
  total: number;
  page: number;
  pageSize: number;
}

export interface SyncStatus {
  running: boolean;
  done: boolean;
  error?: string;
  total: number;
  synced: number;
  updatedAt: number;
  page?: number;
  pageSize?: number;
}

export interface ClassScheduleItem {
  id?: number;
  classRkId?: number;
  dayOfWeek: number;
  period: number;
  startTime: string;
  endTime: string;
  courseId: number;
  courseName: string;
  isActive: boolean;
}

export interface ClassCourseItem {
  id: number;
  name: string;
  courseCode?: string;
}

export interface AttendanceRow {
  studentRkId: number;
  studentCode: string;
  fullName: string;
  email: string;
  status: number;
  statusLabel: string;
  onlineMinutes: number;
  statusEditedByTeacher: boolean;
  pushedToQldtAt?: string;
}

export interface AttendanceShiftInfo {
  startTime?: string;
  endTime?: string;
  courseId?: number;
  courseName?: string;
  isActive?: boolean;
  pushedToQldtAt?: string;
  qldtDirty?: boolean;
}

export const ATTENDANCE_STATUS_OPTIONS = [
  { value: 0, label: 'Nghỉ không phép', short: 'NKP' },
  { value: 1, label: 'Nghỉ có phép', short: 'NCP' },
  { value: 2, label: 'Nghỉ nửa buổi', short: 'Nửa buổi' },
  { value: 3, label: 'Đi học muộn', short: 'Muộn' },
  { value: 4, label: 'Đi học đầy đủ', short: 'Đầy đủ' },
] as const;

export function attendanceStatusClass(status: number): string {
  return `attendance-status--${status}`;
}

export function attendanceStatusLabel(status: number): string {
  return ATTENDANCE_STATUS_OPTIONS.find(o => o.value === status)?.label ?? `Trạng thái ${status}`;
}

export interface StudentSessionLogItem {
  id: number;
  studentRkId: number;
  studentCode: string;
  fullName: string;
  email: string;
  onlineSeconds: number;
  offlineSeconds: number;
  wifiSsids: string;
  lastActiveAt?: string;
}

export const api = {
  getStats: async (): Promise<StatsResponse> => {
    const res = await staffFetch('/stats');
    if (!res.ok) throw new Error('Failed to fetch dashboard stats');
    return res.json();
  },

  getClasses: async (params: {
    page: number;
    pageSize: number;
    q?: string;
    systemRkId?: number;
    studyingOnly?: boolean;
  }): Promise<PaginatedResponse<ClassItem>> => {
    const query = new URLSearchParams({
      page: String(params.page),
      pageSize: String(params.pageSize),
    });
    if (params.q) query.set('q', params.q);
    if (params.systemRkId) query.set('systemRkId', String(params.systemRkId));
    if (params.studyingOnly) query.set('studyingOnly', 'true');

    const res = await staffFetch(`/classes?${query}`);
    if (!res.ok) throw new Error('Failed to fetch classes');
    return res.json();
  },

  updateClassStudying: async (rkId: number, isStudying: boolean): Promise<any> => {
    const res = await staffFetch(`/classes/${rkId}/studying`, {
      method: 'PATCH',
      body: JSON.stringify({ isStudying }),
    });
    if (!res.ok) {
      const errData = await res.json().catch(() => ({}));
      throw new Error(errData.error || 'Failed to update class studying status');
    }
    return res.json();
  },

  getClassStudents: async (rkId: number): Promise<{ data: StudentItem[]; total: number }> => {
    const res = await staffFetch(`/classes/${rkId}/students`);
    if (!res.ok) throw new Error('Failed to fetch class students roster');
    return res.json();
  },

  getClass: async (rkId: number): Promise<ClassItem> => {
    const res = await staffFetch(`/classes/${rkId}`);
    if (!res.ok) throw new Error('Failed to fetch class');
    return res.json();
  },

  getStudents: async (params: {
    page: number;
    pageSize: number;
    q?: string;
  }): Promise<PaginatedResponse<StudentItem>> => {
    const query = new URLSearchParams({
      page: String(params.page),
      pageSize: String(params.pageSize),
    });
    if (params.q) query.set('q', params.q);

    const res = await staffFetch(`/students?${query}`);
    if (!res.ok) throw new Error('Failed to fetch students');
    return res.json();
  },

  startClassesSync: async (): Promise<{ ok: boolean; message: string }> => {
    const res = await staffFetch('/sync/classes/start', { method: 'POST' });
    if (!res.ok) {
      const errData = await res.json().catch(() => ({}));
      throw new Error(errData.error || 'Failed to start classes sync');
    }
    return res.json();
  },

  getClassesSyncStatus: async (): Promise<SyncStatus> => {
    const res = await staffFetch('/sync/classes/status');
    if (!res.ok) throw new Error('Failed to get classes sync status');
    return res.json();
  },

  startStudentsSync: async (): Promise<{ ok: boolean; message: string }> => {
    const res = await staffFetch('/sync/students/start', { method: 'POST' });
    if (!res.ok) {
      const errData = await res.json().catch(() => ({}));
      throw new Error(errData.error || 'Failed to start students sync');
    }
    return res.json();
  },

  getStudentsSyncStatus: async (): Promise<SyncStatus> => {
    const res = await staffFetch('/sync/students/status');
    if (!res.ok) throw new Error('Failed to get students sync status');
    return res.json();
  },
};

// Export individual learning functions to simplify imports in components
export const apiFetchActiveSchedules = async (): Promise<{ data: any[] }> => {
  const res = await staffFetch('/classes/schedules');
  if (!res.ok) throw new Error('Failed to fetch active schedules');
  return res.json();
};

export const apiFetchClassSchedule = async (rkId: number): Promise<{ data: ClassScheduleItem[] }> => {
  const res = await staffFetch(`/classes/${rkId}/schedule`);
  if (!res.ok) throw new Error('Failed to fetch class schedule');
  return res.json();
};

export const apiSaveClassSchedule = async (rkId: number, schedules: ClassScheduleItem[]): Promise<any> => {
  const res = await staffFetch(`/classes/${rkId}/schedule`, {
    method: 'POST',
    body: JSON.stringify({ schedules }),
  });
  if (!res.ok) throw new Error('Failed to save class schedule');
  return res.json();
};

export const apiDeleteClassSchedule = async (rkId: number): Promise<any> => {
  const res = await staffFetch(`/classes/${rkId}/schedule`, { method: 'DELETE' });
  if (!res.ok) throw new Error('Failed to delete class schedule');
  return res.json();
};

export const apiFetchAllowedApps = async (rkId: number): Promise<{ classRkId: number; keywords: string }> => {
  const res = await staffFetch(`/classes/${rkId}/allowed-apps`);
  if (!res.ok) throw new Error('Failed to fetch allowed apps keywords');
  return res.json();
};

export const apiSaveAllowedApps = async (rkId: number, keywords: string): Promise<any> => {
  const res = await staffFetch(`/classes/${rkId}/allowed-apps`, {
    method: 'POST',
    body: JSON.stringify({ keywords }),
  });
  if (!res.ok) throw new Error('Failed to save allowed apps keywords');
  return res.json();
};

export interface AppPoolItem {
  id: number;
  processName: string;
  windowTitle: string;
  keyword: string;
  hitCount: number;
  lastSeenAt: string;
  lastStudentRkId?: number;
  lastClassRkId?: number;
}

export const apiFetchAppPool = async (q = '', limit = 50): Promise<{ data: AppPoolItem[]; q?: string; limit?: number }> => {
  const params = new URLSearchParams();
  if (q.trim()) params.set('q', q.trim());
  params.set('limit', String(limit));
  const query = params.toString() ? `?${params.toString()}` : '';
  const res = await staffFetch(`/app-pool${query}`);
  if (!res.ok) throw new Error('Failed to fetch app pool');
  return res.json();
};

export interface WifiPoolItem {
  id: number;
  ssid: string;
  bssid: string;
  hitCount: number;
  lastSeenAt: string;
  lastStudentRkId?: number;
}

export interface AcceptedWifiItem {
  id: number;
  ssid: string;
  bssid: string;
  createdAt: string;
}

export type WifiAcceptItem = { ssid: string; bssid: string };

export const apiFetchWifiPool = async (q = '', limit = 50): Promise<{ data: WifiPoolItem[] }> => {
  const params = new URLSearchParams();
  if (q.trim()) params.set('q', q.trim());
  params.set('limit', String(limit));
  const query = params.toString() ? `?${params.toString()}` : '';
  const res = await staffFetch(`/wifi-pool${query}`);
  if (!res.ok) throw new Error('Failed to fetch wifi pool');
  return res.json();
};

export const apiFetchAcceptedWifis = async (): Promise<{ data: AcceptedWifiItem[] }> => {
  const res = await staffFetch('/network/accepted-wifis');
  if (!res.ok) throw new Error('Failed to fetch accepted wifis');
  return res.json();
};

export const apiSaveAcceptedWifis = async (items: WifiAcceptItem[]): Promise<any> => {
  const res = await staffFetch('/network/accepted-wifis', {
    method: 'POST',
    body: JSON.stringify({ items }),
  });
  if (!res.ok) throw new Error('Failed to save accepted wifis');
  return res.json();
};

export const apiFetchClassStudents = api.getClassStudents;
export const apiFetchClasses = api.getClasses;

export const apiFetchClassSessionLogs = async (
  rkId: number,
  date?: string,
  period?: number
): Promise<{ data: StudentSessionLogItem[]; period?: number; date?: string }> => {
  const params = new URLSearchParams();
  if (date) params.set('date', date);
  if (period) params.set('period', String(period));
  const query = params.toString() ? `?${params.toString()}` : '';
  const res = await staffFetch(`/classes/${rkId}/session-logs${query}`);
  if (!res.ok) throw new Error('Failed to fetch class session logs');
  return res.json();
};

export const apiFetchOnlineStudents = async (rkId: number): Promise<{ onlineStudentIds: number[] }> => {
  const res = await staffFetch(`/classes/${rkId}/online-students`);
  if (!res.ok) throw new Error('Failed to fetch online students list');
  return res.json();
};

export const apiFetchClassCourses = async (rkId: number): Promise<{
  data: ClassCourseItem[];
  source?: string;
  cached?: boolean;
  warning?: string;
  hint?: string;
}> => {
  const res = await staffFetch(`/classes/${rkId}/courses`);
  const body = await res.json().catch(() => ({}));
  if (!res.ok) {
    throw new Error(body.error || body.hint || 'Không tải được danh sách môn học từ QLĐT');
  }
  return body;
};

export const apiApplyScheduleTemplate = async (rkId: number): Promise<{ created: number; skipped: number }> => {
  const res = await staffFetch(`/classes/${rkId}/schedule/apply-template`, { method: 'POST' });
  if (!res.ok) throw new Error('Failed to apply schedule template');
  return res.json();
};

export const apiFetchAttendanceShifts = async (rkId: number, date?: string) => {
  const q = date ? `?date=${date}` : '';
  const res = await staffFetch(`/classes/${rkId}/attendance/shifts${q}`);
  if (!res.ok) throw new Error('Failed to fetch attendance shifts');
  return res.json();
};

export const apiFetchAttendance = async (rkId: number, date: string, period: number) => {
  const res = await staffFetch(`/classes/${rkId}/attendance?date=${date}&period=${period}`);
  if (!res.ok) throw new Error('Failed to fetch attendance');
  return res.json();
};

export const apiUpdateAttendanceStatus = async (
  rkId: number,
  payload: { date: string; period: number; studentRkId: number; status: number }
) => {
  const res = await staffFetch(`/classes/${rkId}/attendance/status`, {
    method: 'PUT',
    body: JSON.stringify(payload),
  });
  if (!res.ok) {
    const err = await res.json().catch(() => ({}));
    throw new Error(err.error || 'Failed to update attendance status');
  }
  return res.json();
};

export const apiPushAttendanceQLDT = async (rkId: number, date: string, period: number) => {
  const res = await staffFetch(`/classes/${rkId}/attendance/push-qldt`, {
    method: 'POST',
    body: JSON.stringify({ date, period }),
  });
  if (!res.ok) {
    const err = await res.json().catch(() => ({}));
    throw new Error(err.error || 'Failed to push attendance to QLĐT');
  }
  return res.json();
};

async function staffUpload(path: string, form: FormData): Promise<Response> {
  const headers = new Headers();
  const token = getToken();
  if (token) headers.set('Authorization', `Bearer ${token}`);
  return fetch(`${API_BASE}${path}`, { method: 'POST', headers, body: form });
}

export interface ExamRoomItem {
  id: number;
  name: string;
  startTime: string;
  endTime: string;
  allowedApps: string;
  quizUrl: string;
  status: 'draft' | 'ready' | 'ended' | 'cancelled';
  studentCount: number;
  paperCount: number;
  displayStatus: 'draft' | 'ready' | 'active' | 'ended' | 'cancelled';
}

export interface ExamPaperResource {
  id: number;
  examPaperId: number;
  fileName: string;
}

export interface ExamPaper {
  id: number;
  examRoomId: number;
  title: string;
  pdfPath: string;
  sortOrder: number;
  resources: ExamPaperResource[];
}

export interface ExamRoomStudent {
  id: number;
  examRoomId: number;
  studentRkId: number;
  assignedPaperId?: number;
  paperSentAt?: string;
  paperScheduledAt?: string;
  fullName: string;
  studentCode: string;
  email: string;
  avatar?: string;
  paperTitle?: string;
  submitted: boolean;
}

export interface ExamSubmission {
  id: number;
  examRoomId: number;
  studentRkId: number;
  fileName: string;
  createdAt: string;
  fullName: string;
  studentCode: string;
}

export const apiExam = {
  list: async (): Promise<{ data: ExamRoomItem[] }> => {
    const res = await staffFetch('/exam-rooms');
    if (!res.ok) await parseError(res, 'Failed');
    return res.json();
  },
  create: async (payload: { name: string; startTime: string; endTime: string; allowedApps?: string; quizUrl?: string }) => {
    const res = await staffFetch('/exam-rooms', { method: 'POST', body: JSON.stringify(payload) });
    if (!res.ok) await parseError(res, 'Tạo phòng thi thất bại');
    return res.json();
  },
  get: async (id: number) => {
    const res = await staffFetch(`/exam-rooms/${id}`);
    if (!res.ok) await parseError(res, 'Không tìm thấy');
    return res.json() as Promise<{
      room: ExamRoomItem;
      papers: ExamPaper[];
      students: ExamRoomStudent[];
      displayStatus: string;
      editable: boolean;
      prepEditable: boolean;
      canPublish: boolean;
      canUnpublish: boolean;
      canCancel: boolean;
    }>;
  },
  publish: async (id: number) => {
    const res = await staffFetch(`/exam-rooms/${id}/publish`, { method: 'POST' });
    if (!res.ok) {
      const data = await res.json().catch(() => ({})) as { error?: string; issues?: string[] };
      if (data.issues?.length) {
        throw new Error(data.issues.join('\n'));
      }
      throw new Error(data.error || 'Đẩy phòng thi thất bại');
    }
    return res.json();
  },
  unpublish: async (id: number) => {
    const res = await staffFetch(`/exam-rooms/${id}/unpublish`, { method: 'POST' });
    if (!res.ok) await parseError(res, 'Thu hồi thất bại');
    return res.json();
  },
  cancel: async (id: number) => {
    const res = await staffFetch(`/exam-rooms/${id}/cancel`, { method: 'POST' });
    if (!res.ok) await parseError(res, 'Hủy phòng thi thất bại');
    return res.json();
  },
  update: async (id: number, payload: Partial<{ name: string; startTime: string; endTime: string; allowedApps: string; quizUrl: string }>) => {
    const res = await staffFetch(`/exam-rooms/${id}`, { method: 'PATCH', body: JSON.stringify(payload) });
    if (!res.ok) await parseError(res, 'Cập nhật thất bại');
    return res.json();
  },
  remove: async (id: number) => {
    const res = await staffFetch(`/exam-rooms/${id}`, { method: 'DELETE' });
    if (!res.ok) await parseError(res, 'Xóa thất bại');
    return res.json();
  },
  searchStudents: async (q: string) => {
    const res = await staffFetch(`/exam-rooms/search-students?q=${encodeURIComponent(q)}`);
    if (!res.ok) await parseError(res, 'Tìm kiếm thất bại');
    return res.json() as Promise<{ data: { studentRkId: number; fullName: string; studentCode: string; email: string; classCodes: string }[] }>;
  },
  addStudents: async (id: number, studentRkIds: number[]) => {
    const res = await staffFetch(`/exam-rooms/${id}/students`, { method: 'POST', body: JSON.stringify({ studentRkIds }) });
    if (!res.ok) await parseError(res, 'Thêm sinh viên thất bại');
    return res.json();
  },
  removeStudent: async (id: number, studentRkId: number) => {
    const res = await staffFetch(`/exam-rooms/${id}/students/${studentRkId}`, { method: 'DELETE' });
    if (!res.ok) await parseError(res, 'Xóa sinh viên thất bại');
    return res.json();
  },
  fetchOnlineStudents: async (id: number): Promise<{ onlineStudentIds: number[] }> => {
    const res = await staffFetch(`/exam-rooms/${id}/online-students`);
    if (!res.ok) throw new Error('Không tải được trạng thái online');
    return res.json();
  },
  uploadPackage: async (id: number, title: string, pdf: File, resources: File[] = []) => {
    const form = new FormData();
    form.append('title', title);
    form.append('pdf', pdf);
    resources.forEach((f) => form.append('resources', f));
    const res = await staffUpload(`/exam-rooms/${id}/papers`, form);
    if (!res.ok) await parseError(res, 'Tạo gói đề thất bại');
    return res.json();
  },
  uploadPaper: async (id: number, title: string, pdf: File, resources: File[] = []) => {
    return apiExam.uploadPackage(id, title, pdf, resources);
  },
  uploadPackageResources: async (id: number, paperId: number, files: File[]) => {
    const form = new FormData();
    files.forEach((f) => form.append('resources', f));
    const res = await staffUpload(`/exam-rooms/${id}/papers/${paperId}/resources`, form);
    if (!res.ok) await parseError(res, 'Thêm tài nguyên thất bại');
    return res.json();
  },
  uploadResource: async (id: number, paperId: number, file: File) => {
    return apiExam.uploadPackageResources(id, paperId, [file]);
  },
  deletePaper: async (id: number, paperId: number) => {
    const res = await staffFetch(`/exam-rooms/${id}/papers/${paperId}`, { method: 'DELETE' });
    if (!res.ok) await parseError(res, 'Xóa gói đề thất bại');
    return res.json();
  },
  assignRandom: async (id: number) => {
    const res = await staffFetch(`/exam-rooms/${id}/assign-random`, { method: 'POST' });
    if (!res.ok) await parseError(res, 'Chia gói đề thất bại');
    return res.json() as Promise<{ assigned: number; packages: number }>;
  },
  sendPapers: async (id: number, payload?: { scheduledAt?: string; studentRkIds?: number[] }) => {
    const res = await staffFetch(`/exam-rooms/${id}/send-papers`, { method: 'POST', body: JSON.stringify(payload || {}) });
    if (!res.ok) await parseError(res, 'Gửi gói đề thất bại');
    return res.json();
  },
  listSubmissions: async (id: number) => {
    const res = await staffFetch(`/exam-rooms/${id}/submissions`);
    if (!res.ok) await parseError(res, 'Failed');
    return res.json() as Promise<{ data: ExamSubmission[] }>;
  },
  downloadSubmission: (id: number, subId: number) => `${API_BASE}/exam-rooms/${id}/submissions/${subId}/download`,
};
