import { apiGet, apiPut } from "@/lib/api";
import { downloadListExport, type ExportFormat } from "@/lib/export";

/** Mirrors `AttendanceDelivery` on the API. */
export type DeliveryMode = "in_person" | "online" | "offline" | "hybrid";
export type DeliveryFilter = DeliveryMode | "all" | "virtual";

export type StudentStatus = "present" | "late" | "absent" | "temporary_exit" | "unchecked";
export type Completion = "complete" | "partial" | "empty";
export type SmsState = "delivered" | "queued" | "failed" | "none";
export type AlertSeverity = "critical" | "warning" | "info";

export type StudentStatusFilter =
  | StudentStatus
  | "all"
  | "unjustified"
  | "atrisk"
  | "sms"
  | "virtual"
  | "recorded";

export type ListFilter =
  | "all"
  | "complete"
  | "pending"
  | "incomplete"
  | "partial"
  | "empty"
  | "delayed"
  | "virtual";

export type SmsFilter = SmsState | "all";

/** Query shared by every board endpoint. */
export interface BoardQuery {
  from?: string;
  to?: string;
  branchIds?: number[];
  deliveryMode?: DeliveryFilter;
  periodId?: number | null;
  gradeLevelId?: number | null;
  classRoomId?: number | null;
  teacherId?: number | null;
  status?: StudentStatusFilter;
  lists?: ListFilter;
  sms?: SmsFilter;
  q?: string;
  page?: number;
  perPage?: number;
  limit?: number;
}

export interface OptionRow {
  key: string;
  label: string;
}

export interface BranchOption {
  id: number;
  name: string;
}

export interface PeriodOption {
  id: number;
  branch_id: number;
  title: string;
  order: number;
  starts_at: string | null;
  ends_at: string | null;
  label: string;
}

export interface ClassRoomOption {
  id: number;
  name: string;
  branch_id: number;
  grade_level_name: string | null;
}

export interface FilterOptions {
  branches: BranchOption[];
  periods: PeriodOption[];
  grade_levels: Array<{ id: number; name: string | null }>;
  class_rooms: ClassRoomOption[];
  delivery_modes: OptionRow[];
  statuses: OptionRow[];
  sms_states: OptionRow[];
  today: string;
}

export interface StatusTotals {
  present: number;
  late: number;
  absent: number;
  temporary_exit: number;
  unchecked: number;
  total: number;
  presence_rate: number;
  unchecked_pct: number;
}

export interface ListTotals {
  complete: number;
  partial: number;
  empty: number;
  delayed: number;
  total: number;
  pending: number;
  avg_delay_minutes: number;
  late_pct: number;
  on_time_pct: number;
}

export interface ModeCount {
  mode: DeliveryMode;
  label: string;
  sessions: number;
}

export interface DeliveryRow extends StatusTotals {
  mode: DeliveryMode;
  label: string;
  is_virtual: boolean;
  sessions: number;
  lists: ListTotals;
}

export interface BranchRow extends StatusTotals {
  branch_id: number;
  branch_name: string | null;
  sessions: number;
  sessions_by_mode: ModeCount[];
  unjustified_absent: number;
  lists: ListTotals;
}

export interface PeriodRow extends Omit<StatusTotals, "presence_rate" | "unchecked_pct"> {
  period_id: number | null;
  period_title: string;
  period_order: number;
  sessions: number;
}

export interface TrendRow extends StatusTotals {
  date: string;
  sessions: number;
  sessions_by_mode: Record<string, number>;
}

export interface InsightRow {
  id: string;
  severity: AlertSeverity;
  branch_id: number | null;
  branch_name: string | null;
  title: string;
  message: string;
  action: string;
}

export interface PolicyValues {
  absence_cap_days: number;
  late_threshold_minutes: number;
  form_delay_minutes: number;
}

export interface Overview {
  range: {
    from: string;
    to: string;
    days: number;
    working_days: number;
    single_day: boolean;
  };
  scope: {
    branch_ids: number[];
    branches: BranchOption[];
    delivery_mode: DeliveryFilter;
    period_id: number | null;
    grade_level_id: number | null;
    class_room_id: number | null;
  };
  policy: PolicyValues & {
    per_branch: Array<PolicyValues & { branch_id: number; branch_name: string | null }>;
  };
  students: StatusTotals;
  lists: ListTotals;
  delivery: DeliveryRow[];
  branches: BranchRow[];
  periods: PeriodRow[];
  trend: TrendRow[];
  sessions: { total: number; by_mode: ModeCount[] };
  alerts: { open: number; critical: number; warning: number; info: number };
  messages: {
    delivered: number;
    queued: number;
    failed: number;
    none: number;
    total: number;
    last_at: string | null;
  };
  at_risk_students: number;
  unjustified_absent: number;
  presence_source: string;
  insights: InsightRow[];
}

export interface StudentRow {
  id: string;
  date: string;
  enrollment_id: number;
  student_profile_id: number;
  student_name: string;
  student_code: string | null;
  parent_phone: string | null;
  branch_id: number;
  branch_name: string | null;
  class_room_id: number;
  class_name: string | null;
  grade_level_name: string | null;
  schedule_id: number;
  subject_name: string | null;
  teacher_id: number | null;
  teacher_name: string | null;
  period_id: number | null;
  period_title: string | null;
  starts_at: string | null;
  ends_at: string | null;
  delivery_mode: DeliveryMode;
  delivery_mode_label: string;
  is_virtual: boolean;
  status: StudentStatus;
  status_label: string;
  late_minutes: number | null;
  over_late_threshold: boolean;
  late_justified: boolean;
  early_exit_justified: boolean;
  unjustified: boolean;
  note: string | null;
  source: string | null;
  recorded_at: string | null;
  gate_entry_at: string | null;
  teacher_recorded: boolean;
  absence_count: number;
  at_risk: boolean;
  sms_state: SmsState;
  sms_state_label: string;
  sms_sent_at: string | null;
}

export interface ClassRow {
  id: string;
  date: string;
  schedule_id: number;
  branch_id: number;
  branch_name: string | null;
  class_room_id: number;
  class_name: string | null;
  grade_level_name: string | null;
  subject_name: string | null;
  teacher_id: number | null;
  teacher_name: string;
  period_id: number | null;
  period_title: string | null;
  starts_at: string | null;
  ends_at: string | null;
  delivery_mode: DeliveryMode;
  delivery_mode_label: string;
  is_virtual: boolean;
  recorded: number;
  total: number;
  present: number;
  late: number;
  absent: number;
  temporary_exit: number;
  unchecked: number;
  completion: Completion;
  completion_label: string;
  delay_minutes: number | null;
  is_delayed: boolean;
  submitted_at: string | null;
  form_delay_threshold: number;
}

export interface AlertRow {
  id: number;
  severity: AlertSeverity;
  alert_type: string;
  branch_id: number;
  branch_name: string | null;
  title: string;
  detail: string | null;
  delivery_mode: DeliveryMode | null;
  student_profile_id: number | null;
  student_name: string | null;
  student_code: string | null;
  created_at: string | null;
}

/** همان فیلترهای حل‌شدهٔ سرور که همراه ردیف‌ها برمی‌گردد. */
export interface ResolvedFilters {
  branch_ids: number[];
  from: string;
  to: string;
  delivery_mode: DeliveryFilter;
  period_id: number | null;
  grade_level_id: number | null;
  class_room_id: number | null;
  teacher_id: number | null;
  status: string | null;
  lists: string | null;
  sms: string | null;
  q: string | null;
  policy: PolicyValues;
}

export interface StudentRowsPayload {
  rows: StudentRow[];
  total: number;
  page: number;
  per_page: number;
  truncated: boolean;
  counts: Record<StudentStatus | "total", number>;
  filters: ResolvedFilters;
}

export interface ClassRowsPayload {
  rows: ClassRow[];
  total: number;
  page: number;
  per_page: number;
  counts: Record<Completion | "delayed" | "total", number>;
  filters: ResolvedFilters;
}

export interface AlertRowsPayload {
  rows: AlertRow[];
  total: number;
  counts: Record<AlertSeverity | "total", number>;
  filters: ResolvedFilters;
}

export interface PolicyPayload {
  rows: Array<
    PolicyValues & {
      branch_id: number;
      branch_name: string | null;
      morning_absence_cutoff: string;
      late_minute_presets: number[];
      sms_morning_absence_enabled: boolean;
      alert_absent_class_at_school: boolean;
      roll_call_window_seconds: number;
    }
  >;
  effective: PolicyValues;
  scope: "branch" | "multi";
}

const BASE = "/attendance/board";

/**
 * Flattens a `BoardQuery` into the snake_case params the API validates.
 * `all` and empty values are dropped so the server applies its own defaults.
 */
export function boardParams(query: BoardQuery): Record<string, string> {
  const params: Record<string, string> = {};
  const put = (key: string, value: string | number | null | undefined) => {
    if (value === null || value === undefined || value === "" || value === "all") return;
    params[key] = String(value);
  };

  put("from", query.from);
  put("to", query.to);
  if (query.branchIds && query.branchIds.length > 0) {
    params.branch_id = query.branchIds.join(",");
  }
  put("delivery_mode", query.deliveryMode);
  put("period_id", query.periodId);
  put("grade_level_id", query.gradeLevelId);
  put("class_room_id", query.classRoomId);
  put("teacher_id", query.teacherId);
  put("status", query.status);
  put("lists", query.lists);
  put("sms", query.sms);
  put("q", query.q?.trim());
  put("page", query.page);
  put("per_page", query.perPage);
  put("limit", query.limit);

  return params;
}

function url(path: string, query: BoardQuery): string {
  const qs = new URLSearchParams(boardParams(query)).toString();
  return qs ? `${BASE}${path}?${qs}` : `${BASE}${path}`;
}

export function fetchAttendanceFilters(query: BoardQuery): Promise<FilterOptions> {
  return apiGet<FilterOptions>(url("/filters", query));
}

export function fetchAttendanceOverview(query: BoardQuery): Promise<Overview> {
  return apiGet<Overview>(url("/overview", query));
}

export function fetchAttendanceStudents(query: BoardQuery): Promise<StudentRowsPayload> {
  return apiGet<StudentRowsPayload>(url("/students", query));
}

export function fetchAttendanceClasses(query: BoardQuery): Promise<ClassRowsPayload> {
  return apiGet<ClassRowsPayload>(url("/classes", query));
}

export function fetchAttendanceAlerts(query: BoardQuery): Promise<AlertRowsPayload> {
  return apiGet<AlertRowsPayload>(url("/alerts", query));
}

export function fetchAttendancePolicy(query: BoardQuery): Promise<PolicyPayload> {
  return apiGet<PolicyPayload>(url("/policy", query));
}

export function saveAttendancePolicy(input: {
  branch_ids?: number[];
  absence_cap_days?: number;
  late_threshold_minutes?: number;
  form_delay_minutes?: number;
  morning_absence_cutoff?: string;
}): Promise<PolicyPayload> {
  return apiPut<PolicyPayload>(`${BASE}/policy`, input);
}

export type BoardExportKind = "students" | "classes" | "branches";

const EXPORT_NAMES: Record<BoardExportKind, string> = {
  students: "attendance-students",
  classes: "attendance-classes",
  branches: "attendance-branches",
};

export function downloadAttendanceExport(
  kind: BoardExportKind,
  query: BoardQuery,
  format: ExportFormat,
): Promise<void> {
  return downloadListExport(
    `${BASE}/${kind}/export`,
    boardParams(query),
    format,
    "filtered",
    EXPORT_NAMES[kind],
  );
}
