/**
 * Date Formatting Utilities Tests
 * Story 3.1: Testing date formatting for history feed
 */

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { formatRelativeDate, formatFullDate, formatShortDate, formatTime } from './date';

describe('formatRelativeDate', () => {
  let originalDateNow: Date['now'];

  beforeEach(() => {
    // Mock Date.now() to have a fixed reference point
    originalDateNow = Date.now;
    const fixedDate = new Date('2024-01-15T12:00:00Z');
    vi.spyOn(Date, 'now').mockReturnValue(fixedDate.getTime());
  });

  afterEach(() => {
    // Restore original Date.now
    Date.now = originalDateNow;
  });

  it('returns "Today" for same day timestamp', () => {
    const today = new Date('2024-01-15T10:30:00Z').getTime();
    expect(formatRelativeDate(today)).toBe('Today');
  });

  it('returns "Yesterday" for previous day timestamp', () => {
    const yesterday = new Date('2024-01-14T12:00:00Z').getTime();
    expect(formatRelativeDate(yesterday)).toBe('Yesterday');
  });

  it('returns "X days ago" for timestamps less than a week old', () => {
    const threeDaysAgo = new Date('2024-01-12T12:00:00Z').getTime();
    expect(formatRelativeDate(threeDaysAgo)).toBe('3 days ago');

    const sixDaysAgo = new Date('2024-01-09T12:00:00Z').getTime();
    expect(formatRelativeDate(sixDaysAgo)).toBe('6 days ago');
  });

  it('returns "X weeks ago" for timestamps less than a month old', () => {
    const twoWeeksAgo = new Date('2024-01-01T12:00:00Z').getTime();
    expect(formatRelativeDate(twoWeeksAgo)).toBe('2 weeks ago');

    const threeWeeksAgo = new Date('2023-12-25T12:00:00Z').getTime();
    expect(formatRelativeDate(threeWeeksAgo)).toBe('3 weeks ago');
  });

  it('returns formatted date for timestamps from current year', () => {
    const january = new Date('2024-01-01T12:00:00Z').getTime();
    const result = formatRelativeDate(january);
    // Check it contains the date (formatting may vary by locale/timezone)
    expect(result).toContain('Jan');
    expect(result).toContain('1');
  });

  it('returns formatted date with year for timestamps from previous year', () => {
    const lastYear = new Date('2023-12-31T12:00:00Z').getTime();
    const result = formatRelativeDate(lastYear);
    // Check it contains the date and year (formatting may vary by locale/timezone)
    expect(result).toContain('Dec');
    expect(result).toContain('31');
  });

  it('returns "Just now" for future timestamps', () => {
    const future = new Date('2024-01-16T12:00:00Z').getTime();
    expect(formatRelativeDate(future)).toBe('Just now');
  });

  it('handles zero timestamp gracefully', () => {
    expect(formatRelativeDate(0)).toMatch(/1970/);
  });
});

describe('formatFullDate', () => {
  it('formats date with month, day, and year', () => {
    const timestamp = new Date('2024-01-15T12:00:00Z').getTime();
    expect(formatFullDate(timestamp)).toBe('January 15, 2024');
  });

  it('formats different dates correctly', () => {
    const feb29 = new Date('2024-02-29T12:00:00Z').getTime();
    expect(formatFullDate(feb29)).toBe('February 29, 2024');
  });
});

describe('formatShortDate', () => {
  it('formats date with month and day only', () => {
    const timestamp = new Date('2024-01-15T12:00:00Z').getTime();
    expect(formatShortDate(timestamp)).toBe('Jan 15');
  });

  it('formats leap day correctly', () => {
    const feb29 = new Date('2024-02-29T12:00:00Z').getTime();
    expect(formatShortDate(feb29)).toBe('Feb 29');
  });
});

describe('formatTime', () => {
  it('formats time in 12-hour format', () => {
    const morning = new Date('2024-01-15T09:30:00Z').getTime();
    const morningResult = formatTime(morning);
    expect(morningResult).toMatch(/AM/);
    expect(morningResult).toContain('30');

    const afternoon = new Date('2024-01-15T14:45:00Z').getTime();
    const afternoonResult = formatTime(afternoon);
    expect(afternoonResult).toMatch(/PM/);
    expect(afternoonResult).toContain('45');
  });

  it('handles midnight and noon', () => {
    const midnight = new Date('2024-01-15T00:00:00Z').getTime();
    const midnightResult = formatTime(midnight);
    expect(midnightResult).toMatch(/AM/);

    const noon = new Date('2024-01-15T12:00:00Z').getTime();
    const noonResult = formatTime(noon);
    expect(noonResult).toMatch(/PM/);
  });
});
