import { describe, expect, it } from 'vitest';
import { displayJoinUrl, formatClock, formatEventTime, formatPoints, formatSeconds, formatTeamScore, optionLetter, safeTimeZone, secondsLeft } from './format';

describe('number formatting', () => {
  it('formats points with separators and a real minus sign', () => {
    expect(formatPoints(3844)).toBe('3,844');
    expect(formatPoints(-100)).toBe('−100');
    expect(formatPoints(0)).toBe('0');
  });

  it('formats team means with at most one decimal', () => {
    expect(formatTeamScore(412.5)).toBe('412.5');
    expect(formatTeamScore(400)).toBe('400');
    expect(formatTeamScore(1234.04)).toBe('1,234');
  });

  it('formats answer speed in seconds to one decimal', () => {
    expect(formatSeconds(5585)).toBe('5.6s');
    expect(formatSeconds(940)).toBe('0.9s');
    expect(formatSeconds(-20)).toBe('0.0s');
  });
});

describe('countdowns', () => {
  it('rounds seconds up so the last second is shown until it ends', () => {
    expect(secondsLeft(14_001)).toBe(15);
    expect(secondsLeft(1)).toBe(1);
    expect(secondsLeft(0)).toBe(0);
    expect(secondsLeft(-500)).toBe(0);
  });

  it('formats clocks as m:ss or h:mm:ss', () => {
    expect(formatClock(42_000)).toBe('0:42');
    expect(formatClock(60_000)).toBe('1:00');
    expect(formatClock(3_725_000)).toBe('1:02:05');
    expect(formatClock(0)).toBe('0:00');
  });
});

describe('optionLetter', () => {
  it('labels options A, B, C, D', () => {
    expect([0, 1, 2, 3].map(optionLetter)).toEqual(['A', 'B', 'C', 'D']);
  });
});

describe('formatEventTime', () => {
  const NY = 'America/New_York';
  // 2026-10-29 20:00 UTC = 4:00 PM in New York (EDT).
  const now = Date.UTC(2026, 9, 29, 20, 0);

  it('says "Tonight" for later the same evening and "Today" for earlier hours', () => {
    expect(formatEventTime(Date.UTC(2026, 9, 30, 0, 0), now, NY)).toBe('Tonight · 8:00 PM');
    expect(formatEventTime(Date.UTC(2026, 9, 29, 20, 30), now, NY)).toBe('Today · 4:30 PM');
  });

  it('uses the venue time zone for the calendar day', () => {
    // 01:00 UTC on the 30th is still the 29th in New York.
    expect(formatEventTime(Date.UTC(2026, 9, 30, 1, 0), now, NY)).toBe('Tonight · 9:00 PM');
    expect(formatEventTime(Date.UTC(2026, 9, 31, 0, 0), now, NY)).toBe('Tomorrow · 8:00 PM');
  });

  it('uses the weekday within a week and the date beyond', () => {
    expect(formatEventTime(Date.UTC(2026, 10, 1, 0, 0), now, NY)).toBe('Sat · 8:00 PM');
    expect(formatEventTime(Date.UTC(2026, 10, 14, 1, 0), now, NY)).toBe('Nov 13 · 8:00 PM');
  });

  it('falls back to UTC for an invalid zone instead of throwing', () => {
    expect(safeTimeZone('Not/AZone')).toBe('UTC');
    expect(safeTimeZone(null)).toBe('UTC');
    expect(safeTimeZone(NY)).toBe(NY);
    expect(formatEventTime(Date.UTC(2026, 9, 29, 21, 0), now, 'Not/AZone')).toBe('Tonight · 9:00 PM');
  });
});

describe('displayJoinUrl', () => {
  it('prints the short host/join/CODE form', () => {
    expect(displayJoinUrl('https://www.pintrush.com/', 'HARBOR')).toBe('pintrush.com/join/HARBOR');
    expect(displayJoinUrl('http://localhost:3000', 'DEMO')).toBe('localhost:3000/join/DEMO');
  });
});
