import { describe, it, expect } from 'vitest';
import { currentPeriodYearMonth, isValidPeriod } from './period.js';

describe('currentPeriodYearMonth', () => {
  it('formats a typical UTC Date', () => {
    expect(currentPeriodYearMonth(new Date(Date.UTC(2026, 4, 15, 12, 0, 0)))).toBe('2026-05');
  });

  it('zero-pads single-digit months', () => {
    expect(currentPeriodYearMonth(new Date(Date.UTC(2026, 0, 1, 0, 0, 0)))).toBe('2026-01');
    expect(currentPeriodYearMonth(new Date(Date.UTC(2026, 8, 30, 0, 0, 0)))).toBe('2026-09');
  });

  it('uses UTC, not local time', () => {
    // 2025-12-31 23:59:59 UTC = '2025-12'. If implementation used local
    // time, in a +09:00 timezone (JST) this would already be the next
    // day → '2026-01'. We hard-pin UTC by always passing in UTC dates.
    const lastSecOfYear = new Date(Date.UTC(2025, 11, 31, 23, 59, 59));
    expect(currentPeriodYearMonth(lastSecOfYear)).toBe('2025-12');
    const firstSecOfNextYear = new Date(Date.UTC(2026, 0, 1, 0, 0, 0));
    expect(currentPeriodYearMonth(firstSecOfNextYear)).toBe('2026-01');
  });

  it('handles month-end correctly', () => {
    expect(currentPeriodYearMonth(new Date(Date.UTC(2026, 1, 28, 23, 59, 59)))).toBe('2026-02');
    // Feb 29 in leap year still maps to '2026' Feb? 2026 isn't a leap year;
    // the Date constructor would normalize to March 1 — confirm UTC handling.
    expect(currentPeriodYearMonth(new Date(Date.UTC(2026, 1, 29, 0, 0, 0)))).toBe('2026-03');
  });

  it('returns lexicographically comparable strings', () => {
    expect(currentPeriodYearMonth(new Date(Date.UTC(2026, 0, 1, 0, 0, 0))) <
           currentPeriodYearMonth(new Date(Date.UTC(2026, 11, 1, 0, 0, 0)))).toBe(true);
    expect(currentPeriodYearMonth(new Date(Date.UTC(2026, 9, 1, 0, 0, 0))) <
           currentPeriodYearMonth(new Date(Date.UTC(2026, 10, 1, 0, 0, 0)))).toBe(true);
  });
});

describe('isValidPeriod', () => {
  it.each([
    ['2026-01', true],
    ['2026-12', true],
    ['1970-01', true],
  ])('accepts %s', (p, exp) => expect(isValidPeriod(p)).toBe(exp));

  it.each([
    ['2026-13', false],
    ['2026-00', false],
    ['2026-1', false],
    ['202-01', false],
    ['', false],
  ])('rejects %s', (p, exp) => expect(isValidPeriod(p)).toBe(exp));

  it('rejects non-string', () => {
    expect(isValidPeriod(undefined)).toBe(false);
    expect(isValidPeriod(null)).toBe(false);
    expect(isValidPeriod(2026)).toBe(false);
    expect(isValidPeriod({})).toBe(false);
  });
});
