/**
 * Display formatting shared by host and admin screens (server and client). Venue times are always
 * shown in the venue's own time zone, never the viewer's, so a host on a laptop set to another zone
 * still sees "Fri 9:00 PM" for a 9 PM show.
 */

export function formatDateTime(value: Date | number | null | undefined, timeZone: string, style: 'full' | 'short' = 'short'): string {
  if (value === null || value === undefined) return '—';
  const date = typeof value === 'number' ? new Date(value) : value;
  if (Number.isNaN(date.getTime())) return '—';
  return new Intl.DateTimeFormat('en-US', {
    timeZone,
    weekday: 'short',
    month: 'short',
    day: 'numeric',
    ...(style === 'full' ? { year: 'numeric' } : {}),
    hour: 'numeric',
    minute: '2-digit',
  }).format(date);
}

export function formatDate(value: Date | number | null | undefined, timeZone: string): string {
  if (value === null || value === undefined) return '—';
  const date = typeof value === 'number' ? new Date(value) : value;
  if (Number.isNaN(date.getTime())) return '—';
  return new Intl.DateTimeFormat('en-US', { timeZone, month: 'short', day: 'numeric', year: 'numeric' }).format(date);
}

/** 'YYYY-MM-DD' business date → "Thu, Oct 29" (calendar date, no zone maths). */
export function formatBusinessDate(date: string): string {
  const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(date);
  if (!m) return date;
  return new Intl.DateTimeFormat('en-US', { timeZone: 'UTC', weekday: 'short', month: 'short', day: 'numeric' }).format(
    new Date(Date.UTC(Number(m[1]), Number(m[2]) - 1, Number(m[3]))),
  );
}

/** Short zone label for a venue, e.g. "EDT". */
export function zoneAbbreviation(timeZone: string, at: number = Date.now()): string {
  const part = new Intl.DateTimeFormat('en-US', { timeZone, timeZoneName: 'short' }).formatToParts(at).find((p) => p.type === 'timeZoneName');
  return part?.value ?? timeZone;
}

const numberFormat = new Intl.NumberFormat('en-US');
export function formatNumber(n: number): string {
  return numberFormat.format(n);
}

export function formatPercent(fraction: number): string {
  if (!Number.isFinite(fraction)) return '—';
  return `${Math.round(fraction * 100)}%`;
}

export function formatPrice(cents: number, interval: string): string {
  return `${new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 }).format(cents / 100)}/${interval === 'month' ? 'mo' : interval}`;
}

/** mm:ss (or h:mm:ss) for countdowns. */
export function formatClock(ms: number): string {
  const total = Math.max(0, Math.ceil(ms / 1000));
  const h = Math.floor(total / 3600);
  const m = Math.floor((total % 3600) / 60);
  const s = total % 60;
  const mm = h > 0 ? String(m).padStart(2, '0') : String(m);
  return `${h > 0 ? `${h}:` : ''}${mm}:${String(s).padStart(2, '0')}`;
}

/** "in 3 days", "in 2 h", "5 min ago" relative to `now`. */
export function formatRelative(target: number, now: number): string {
  const diff = target - now;
  const abs = Math.abs(diff);
  const units: [number, string][] = [
    [86_400_000, 'day'],
    [3_600_000, 'hour'],
    [60_000, 'minute'],
  ];
  for (const [size, unit] of units) {
    if (abs >= size) {
      const n = Math.round(abs / size);
      const label = `${n} ${unit}${n === 1 ? '' : 's'}`;
      return diff >= 0 ? `in ${label}` : `${label} ago`;
    }
  }
  return diff >= 0 ? 'in under a minute' : 'just now';
}

export const ROUND_KIND_LABELS = {
  RUSH: 'The Rush',
  MUSIC_MAYHEM: 'Music Mayhem',
  TABLE_WARS: 'Table Wars',
  POWER_ROUND: 'Power Round',
  FINAL_RUSH: 'Final Rush',
} as const;

export type RoundKindName = keyof typeof ROUND_KIND_LABELS;
export const ROUND_KINDS = Object.keys(ROUND_KIND_LABELS) as RoundKindName[];

export const WEEKDAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] as const;
