import { ProgramUserAttendance } from 'src/common/entities';
import { OnlineTypeEnum } from 'src/common/enum/online-type.enum';
import { SessionLaunchMode } from 'src/common/enum/session-launch-mode.enum';
import { AttendanceEvent } from 'src/common/interfaces/attendance-event.interface';
import { AttendanceStatus } from 'src/common/enum/attendance-status.enum';
import { AttendanceSourceEnum } from 'src/common/enum/attendance-source.enum';

/** Filter + pagination for a per-session attendance listing. */
export interface SessionAttendanceFilter {
  page: number;
  limit: number;
  isAttended?: boolean;
  search?: string;
}

/** A page of attendance rows with the total match count. */
export interface PaginatedAttendance {
  data: ProgramUserAttendance[];
  total: number;
}

/** Count of distinct attendees per attendance source. */
export type AttendanceBreakdown = Record<string, number>;

/** Join-time client metadata captured on join-click, keyed by lowercased email. */
export interface AttendanceClientMeta {
  modeOfJoining: string | null;
  deviceType: string | null;
  deviceInfo: string | null;
  /** True when credited via another person's device (a "join with others" companion). */
  joinWithOthers: boolean;
  /** Whether this person was marked attended (any source). */
  attended: boolean;
  fullName: string | null;
}

/** Result of a participant join-click: the join link + marked-attendance flag. */
export interface JoinSessionResult {
  joinUrl: string;
  onlineType: OnlineTypeEnum;
  /** Where to launch: embedded SDK (in-app) vs the Zoom client/web. */
  launchMode: SessionLaunchMode;
  meetingId: string | null;
  meetingPassword: string | null;
  attendanceMarked: boolean;
}

/** One attendee row in a session attendance report. */
export interface AttendanceRecord {
  attendanceId: number;
  userId: number;
  fullName: string;
  email: string;
  mobile: string;
  isAttended: boolean;
  /** Resolved effective attendance status (SESSION_ATTENDANCE): present | absent | unknown. */
  attendanceStatus: AttendanceStatus;
  /** The source that decided the attendance status, or null when unknown. */
  decidedBySource: AttendanceSourceEnum | null;
  checkedInAt: Date | null;
  attendanceEvents: AttendanceEvent[];
}

/** Per-session aggregate row (shared by session + program reports). */
export interface SessionReportSummary {
  sessionId: number;
  sessionName: string;
  startsAt?: Date;
  totalRegistrants: number;
  totalAttended: number;
  attendanceRate: string;
  breakdown: AttendanceBreakdown;
}

/** Full attendance report for a single session, with paginated rows. */
export interface SessionAttendanceReport {
  sessionId: number;
  sessionName: string;
  totalRegistrants: number;
  totalAttended: number;
  attendanceRate: string;
  breakdown: AttendanceBreakdown;
  records: AttendanceRecord[];
  pagination: { page: number; limit: number; total: number };
}

/** Attendance report aggregated across all sessions of a program. */
export interface ProgramAttendanceReport {
  programId: number;
  sessions: SessionReportSummary[];
  overallAttendanceRate: string;
}

/**
 * One registrant's own RM/Coordinator manual marks for a session — `null` when that source never
 * marked them, independent of which source's mark actually won the resolved `attendanceStatus`.
 * Returned by `OnlineAttendanceService.getManualMarksBySession` for cross-module consumers (the zoom
 * module's seeker table) that need these two flags without importing `ProgramUserAttendance` directly.
 * Also carries the resolved effective status (`attendanceStatus`/`decidedBySource`, from the same
 * precedence engine — see `resolveAttendanceStatus`) — the seeker table's "Final" column.
 */
export interface RegistrationManualMarks {
  registrationId: number;
  rm: boolean | null;
  coordinator: boolean | null;
  attendanceStatus: AttendanceStatus;
  decidedBySource: AttendanceSourceEnum | null;
}

/**
 * A seeker matched against the zoom roster, for `OnlineAttendanceService.recordZoomJoin` — called the
 * moment Zoom's own participant_joined webhook fires, so this seeker's ZOOM_WEBHOOK mark lands in
 * program_user_attendance.attendance_events alongside any RM/Coordinator/Admin/QR/join-click mark, for
 * the same precedence engine to resolve.
 */
export interface RecordZoomJoinParams {
  sessionId: number;
  programId: number;
  registrationId: number;
  userId: number | null;
  fullName: string | null;
  email: string | null;
  mobile: string | null;
  occurredAt: Date;
}

/** A session's current attendance-lock state, returned by lock/unlock. */
export interface SessionAttendanceLockRecord {
  sessionId: number;
  isAttendanceLocked: boolean;
  attendanceLockedBy: number | null;
  attendanceLockedAt: Date | null;
}
