import { toTitleCase, replaceUnderscoreWithSpace } from './common.util';
import { ApprovalStatusEnum } from '../enum/approval-status.enum';
import { InvoiceStatusEnum } from '../enum/invoice-status.enum';
import { PaymentStatusEnum } from '../enum/payment-status.enum';
import { RegistrationStatusEnum } from '../enum/registration-status.enum';
import { RegistrationSubStatusEnum } from '../enum/registration-sub-status.enum';
import { TravelStatusEnum } from '../enum/travel-status.enum';
import { ROLE_KEYS } from '../constants/strings-constants';

function titleCaseStatus(value: unknown): string {
  if (!value) return '';
  return toTitleCase(replaceUnderscoreWithSpace(String(value)));
}

export function formatApprovalStatus(value: ApprovalStatusEnum | string): string {
  switch (value) {
    case ApprovalStatusEnum.PENDING:      return 'Unassigned';
    case ApprovalStatusEnum.APPROVED:     return 'Blessed';
    case ApprovalStatusEnum.ON_HOLD:      return 'Swap Demand';
    case ApprovalStatusEnum.REJECTED:     return 'Hold';
    case ApprovalStatusEnum.CANCELLED:    return 'Cancelled';
    case ApprovalStatusEnum.UNDER_REVIEW: return 'Under Review';
    case 'save_as_draft':                 return 'Draft';
    default:                              return titleCaseStatus(value);
  }
}

export function formatRegistrationStatus(value: RegistrationStatusEnum | string): string {
  switch (value) {
    case RegistrationStatusEnum.DRAFT:            return 'Draft';
    case RegistrationStatusEnum.SAVE_AS_DRAFT:    return 'Draft';
    case RegistrationStatusEnum.ATTEMPTED:        return 'Attempted';
    case RegistrationStatusEnum.PENDING_APPROVAL: return 'Pending Approval';
    case RegistrationStatusEnum.PENDING:          return 'Pending';
    case RegistrationStatusEnum.WAITLISTED:       return 'Waitlisted';
    case RegistrationStatusEnum.COMPLETED:        return 'Completed';
    case RegistrationStatusEnum.CANCELLED:        return 'Cancelled';
    case RegistrationStatusEnum.REJECTED:         return 'Rejected';
    case RegistrationStatusEnum.ON_HOLD:          return 'On Hold';
    case RegistrationStatusEnum.ARCHIVED:         return 'Archived';
    default:                                       return titleCaseStatus(value);
  }
}

export function formatRegistrationStatusApproval(
  value: RegistrationStatusEnum | string,
  approvalStatus: string | null | undefined,
): string {
  if (approvalStatus) return formatApprovalStatus(approvalStatus);
  switch (value) {
    case RegistrationStatusEnum.ON_HOLD:  return 'Swap Demand';
    case RegistrationStatusEnum.REJECTED: return 'Hold';
    case ApprovalStatusEnum.APPROVED:     return 'Blessed';
    default:                              return formatRegistrationStatus(value);
  }
}

export function formatPaymentStatus(
  status: PaymentStatusEnum | string,
  allocatedProgramId: number | null,
  isFreeSeat: boolean,
): string | null {
  switch (status) {
    case PaymentStatusEnum.ONLINE_PENDING:    return 'Online Pending';
    case PaymentStatusEnum.OFFLINE_PENDING:   return 'Offline Pending';
    case PaymentStatusEnum.ONLINE_COMPLETED:  return 'Online Completed';
    case PaymentStatusEnum.OFFLINE_COMPLETED: return 'Offline Completed';
    case PaymentStatusEnum.FAILED:            return 'Failed';
    case PaymentStatusEnum.DRAFT:             return 'Draft';
    case PaymentStatusEnum.SAVE_AS_DRAFT:     return '-';
    case 'payment_pending':                   return 'Pending';
    case '':
      if (allocatedProgramId && !isFreeSeat) return 'Pending';
      if (allocatedProgramId && isFreeSeat)  return 'No Payment';
      return null;
    default:
      return titleCaseStatus(status);
  }
}

export function formatInvoiceStatus(
  status: InvoiceStatusEnum | string,
  allocatedProgramId: number | null,
  isFreeSeat: boolean,
  paymentStatus: PaymentStatusEnum | string | null,
): string | null {
  const isPaymentCompleted =
    paymentStatus === PaymentStatusEnum.OFFLINE_COMPLETED ||
    paymentStatus === PaymentStatusEnum.ONLINE_COMPLETED;
  switch (status) {
    case InvoiceStatusEnum.INVOICE_PENDING:   return 'Pending';
    case InvoiceStatusEnum.INVOICE_COMPLETED: return 'Completed';
    case InvoiceStatusEnum.DRAFT:             return isPaymentCompleted ? 'Pending' : '-';
    case InvoiceStatusEnum.SAVE_AS_DRAFT:     return '-';
    case 'invoice_failed':                    return 'Failed';
    case 'failed':                            return 'Failed';
    case '':
      if (allocatedProgramId && !isFreeSeat && isPaymentCompleted) return 'Pending';
      if (allocatedProgramId && isFreeSeat) return 'No Payment';
      return '-';
    default:
      return titleCaseStatus(status);
  }
}

export function formatTravelStatus(
  status: TravelStatusEnum | string,
  allocatedProgramId: number | null,
): string | null {
  switch (status) {
    case TravelStatusEnum.PENDING:   return 'Pending';
    case TravelStatusEnum.COMPLETED: return 'Completed';
    case TravelStatusEnum.DRAFT:     return 'Draft';
    case TravelStatusEnum.SAVE_AS_DRAFT: return '-';
    case 'travel_pending':           return 'Pending';
    case 'travel_completed':         return 'Completed';
    case '':                         return allocatedProgramId ? 'Pending' : null;
    default:                         return titleCaseStatus(status);
  }
}

export function formatRegistrationStatusWaitlist(
  value: RegistrationStatusEnum | string,
  subStatus: string | null | undefined,
): string {
  if (value === RegistrationStatusEnum.REJECTED) {
    return subStatus === RegistrationSubStatusEnum.DENIED ? 'Denied' : 'On Hold';
  }
  return formatRegistrationStatus(value);
}

export function formatRegistrationStatusApprovalWaitlist(
  value: RegistrationStatusEnum | string,
  subStatus: string | null | undefined,
  approvalStatus: string | null | undefined,
): string {
  if (subStatus === RegistrationSubStatusEnum.DENIED) return 'Denied';
  if (approvalStatus) return formatApprovalStatus(approvalStatus);
  if (value === RegistrationStatusEnum.REJECTED) return 'On Hold';
  if (value === RegistrationStatusEnum.ON_HOLD)  return 'Swap Demand';
  return formatRegistrationStatus(value);
}

// ── Unified "Seeker Status" ───────────────────────────────────────────────────
// Single source of truth used by BOTH the dashboard list (registration.service.ts)
// and the reports module (report-formatter.util.ts). Mirrors the dashboard KPI logic.

// Approval status -> seeker status label (approval-driven programs, e.g. HDB/MSD)
const SEEKER_APPROVAL_STATUS_LABELS: Record<string, string> = {
  [ApprovalStatusEnum.APPROVED]:  'Blessed',
  [ApprovalStatusEnum.PENDING]:   'Unassigned',
  [ApprovalStatusEnum.ON_HOLD]:   'Swap Demand',
  [ApprovalStatusEnum.REJECTED]:  'On Hold',
  [ApprovalStatusEnum.CANCELLED]: 'Cancelled',
};

// Payment status -> seeker status label (non-approval programs, e.g. webinars)
const SEEKER_PAYMENT_STATUS_LABELS: Record<string, string> = {
  [PaymentStatusEnum.ONLINE_COMPLETED]:  'Online Completed',
  [PaymentStatusEnum.OFFLINE_COMPLETED]: 'Offline Completed',
  [PaymentStatusEnum.ONLINE_PENDING]:    'Online Payment Pending',
  [PaymentStatusEnum.OFFLINE_PENDING]:   'Offline Payment Pending',
  [PaymentStatusEnum.FAILED]:            'Payment Failed',
};

export interface SeekerStatusContext {
  registrationStatus?: string | null;
  approvalStatus?: string | null;
  subStatus?: string | null;
  reservedLink?: boolean | null;
  isFreeSeat?: boolean | null;
  paymentStatus?: string | null;
  requiresApproval?: boolean | null;
  waitlistApplicable?: boolean | null;
}

/**
 * Compute the display "Seeker Status" from a registration's full context.
 * Precedence: waitlist-denied → waitlist states → cancelled → approval-driven
 * (approval programs) → draft/completed/rejected → first-page-pending → payment label.
 */
export function computeSeekerStatus(ctx: SeekerStatusContext): string {
  const { registrationStatus, approvalStatus, subStatus, reservedLink, isFreeSeat, paymentStatus, requiresApproval } = ctx;

  // Completed / archived take top priority over every other state
  if (registrationStatus === RegistrationStatusEnum.ARCHIVED) return 'Archived';

  // Rejected with DENIED sub-status = waitlist denied (proper message)
  if (subStatus === RegistrationSubStatusEnum.DENIED) return 'Waitlist Denied';

  // Waitlist / terminal registration states take precedence
  if (registrationStatus === RegistrationStatusEnum.WAITLISTED) {
    return reservedLink === true ? 'Seat Released' : 'Waiting List';
  }
  if (registrationStatus === RegistrationStatusEnum.CANCELLED) return 'Cancelled';

  // Approval-driven programs: status comes from the approval record
  if (requiresApproval) {
    return SEEKER_APPROVAL_STATUS_LABELS[approvalStatus ?? ''] ?? formatRegistrationStatus(registrationStatus ?? '');
  }

  // Non-approval programs (e.g. TAT/entrainment webinars): registration + payment driven
  if (registrationStatus === RegistrationStatusEnum.SAVE_AS_DRAFT || registrationStatus === RegistrationStatusEnum.DRAFT) return 'Draft';
  // For non-approval (waitlist) programs a rejected registration is a denied waitlister
  if (registrationStatus === RegistrationStatusEnum.REJECTED) return 'Waitlist Denied';

    if (registrationStatus === RegistrationStatusEnum.COMPLETED) return 'Completed';


  // First page pending: registration done but NO payment record yet (and not a free seat).
  // If a payment exists (pending / failed / completed), show its specific status instead.
  if (!paymentStatus && isFreeSeat !== true) return 'First Page Pending';

  return SEEKER_PAYMENT_STATUS_LABELS[paymentStatus ?? ''] ?? formatRegistrationStatus(registrationStatus ?? '');
}

// ── General-attendee report "Type" column ─────────────────────────────────────
// fn_generate_general_attendees_report's sourceTag column is the matched
// zoom_generated_registrant_link's raw role_key (a ROLE_* key for a role-matched
// link, the literal 'SYSTEM' for a placeholder link, or 'Unidentified' for no
// match) — see that migration's own header. Mirrors the live General Attendees
// screen's own role-key mapping (GeneralAttendeesTable.tsx's ROLE_DISPLAY_MAPPING/
// resolveSourceTagBadge) so the downloaded report and the live screen never show
// different labels for the same role.
const SOURCE_TAG_ROLE_LABELS: Record<string, string> = {
  [ROLE_KEYS.RELATIONAL_MANAGER]: 'RM',
  [ROLE_KEYS.SHOBA]: 'Coordinator',
  [ROLE_KEYS.ADMIN]: 'Admin',
  [ROLE_KEYS.FINANCE_MANAGER]: 'FM'
};

export function formatSourceTagRole(value: string): string {
  if (SOURCE_TAG_ROLE_LABELS[value]) return SOURCE_TAG_ROLE_LABELS[value];
  if (!value.startsWith('ROLE_')) return value;
  const roleKey = value.slice('ROLE_'.length).toLowerCase();
  return roleKey.charAt(0).toUpperCase() + roleKey.slice(1);
}
