import type { LicenseApplication } from '@ema-platform/api';
import type { MyRegistration } from '../exams/pages/ExamsPage';

/**
 * Where a candidate actually stands in the examination leg.
 *
 * The application's own status cannot answer this on its own. It knows the
 * fee was paid and, later, whether the candidate passed — but registering for
 * a sitting, being marked present and sitting the paper all happen on the
 * registration and the attempt, and the portal was reading none of them. That
 * is why an application could still read "Awaiting Exam Date" after the back
 * office had already evaluated the paper.
 *
 * Every value below is read off server state (application status, attendance
 * ruling, attempt status). Nothing here decides anything the backend has not
 * already recorded — this only names what the records add up to.
 */
export type ExamStage =
  | 'ELIGIBLE_TO_REGISTER'
  | 'REGISTERED'
  | 'ATTENDANCE_CONFIRMED'
  | 'SITTING'
  | 'UNDER_EVALUATION'
  | 'PASSED'
  | 'FAILED';

/** Attendance rulings that mean an invigilator confirmed the candidate. */
const CONFIRMED = ['PRESENT', 'LATE'];

/**
 * Null for anything outside the examination leg, so callers can fall back to
 * the ordinary status label without a second condition.
 */
export function examStageFor(
  // Widened to the raw string rather than LicenseStatus: two screens read
  // applications from different endpoints, and only one of them types the
  // status as the enum.
  app: { status: LicenseApplication['status'] | string },
  registration?: MyRegistration,
): ExamStage | null {
  if (app.status === 'EXAM_PASSED') return 'PASSED';
  if (app.status === 'EXAM_FAILED') return 'FAILED';

  // EXAM_PAID is "prerequisites done, sitting not yet chosen": the fee has
  // cleared and nothing is left but for the candidate to pick a session.
  if (app.status === 'EXAM_PAID') return 'ELIGIBLE_TO_REGISTER';

  if (app.status !== 'EXAM_SCHEDULED') return null;

  // Registered, but the row has not caught up yet — the application only
  // reaches EXAM_SCHEDULED by the candidate registering, so this is a
  // fetch-ordering gap rather than a real state.
  if (!registration) return 'REGISTERED';

  const attempt = registration.attempt?.status;
  if (attempt === 'SUBMITTED' || attempt === 'EXPIRED') return 'UNDER_EVALUATION';
  if (attempt === 'IN_PROGRESS') return 'SITTING';
  if (CONFIRMED.includes(registration.attendanceStatus)) return 'ATTENDANCE_CONFIRMED';
  return 'REGISTERED';
}

/** The registration that answers one application, if the candidate has one. */
export function registrationForApplication(
  applicationId: string,
  registrations: MyRegistration[] | undefined,
): MyRegistration | undefined {
  return registrations?.find((r) => r.applicationId === applicationId);
}
