import { describe, expect, it } from 'vitest';

import {
    RacingDomainValidationError,
} from '../errors/RacingDomainError';

import { LeagueTimezone } from './LeagueTimezone';
import { MonthlyRecurrencePattern } from './MonthlyRecurrencePattern';
import { RaceTimeOfDay } from './RaceTimeOfDay';
import { RecurrenceStrategyFactory } from './RecurrenceStrategy';
import { SeasonSchedule } from './SeasonSchedule';
import { WeekdaySet } from './WeekdaySet';

describe('SeasonSchedule', () => {
  const timeOfDay = RaceTimeOfDay.fromString('20:00');
  const timezone = LeagueTimezone.create('Europe/Berlin');
  const startDate = new Date('2024-01-01');

  it('creates a valid schedule with weekly recurrence', () => {
    const recurrence = RecurrenceStrategyFactory.weekly(WeekdaySet.fromArray(['Mon', 'Wed', 'Fri']));
    const schedule = new SeasonSchedule({
      startDate,
      timeOfDay,
      timezone,
      recurrence,
      plannedRounds: 10,
    });

    expect(schedule.startDate.getFullYear()).toBe(2024);
    expect(schedule.startDate.getMonth()).toBe(0); // January is 0
    expect(schedule.startDate.getDate()).toBe(1);
    expect(schedule.startDate.getHours()).toBe(0);
    expect(schedule.startDate.getMinutes()).toBe(0);
    expect(schedule.startDate.getSeconds()).toBe(0);
    expect(schedule.timeOfDay.equals(timeOfDay)).toBe(true);
    expect(schedule.timezone.equals(timezone)).toBe(true);
    expect(schedule.recurrence).toEqual(recurrence);
    expect(schedule.plannedRounds).toBe(10);
  });

  it('throws when startDate is invalid', () => {
    const recurrence = RecurrenceStrategyFactory.weekly(WeekdaySet.fromArray(['Mon']));
    expect(
      () =>
        new SeasonSchedule({
          startDate: new Date('invalid'),
          timeOfDay,
          timezone,
          recurrence,
          plannedRounds: 10,
        }),
    ).toThrow(RacingDomainValidationError);
  });

  it('throws when plannedRounds is not positive integer', () => {
    const recurrence = RecurrenceStrategyFactory.weekly(WeekdaySet.fromArray(['Mon']));
    expect(
      () =>
        new SeasonSchedule({
          startDate,
          timeOfDay,
          timezone,
          recurrence,
          plannedRounds: 0,
        }),
    ).toThrow(RacingDomainValidationError);

    expect(
      () =>
        new SeasonSchedule({
          startDate,
          timeOfDay,
          timezone,
          recurrence,
          plannedRounds: -1,
        }),
    ).toThrow(RacingDomainValidationError);
  });

  it('equals compares all props', () => {
    const recurrence1 = RecurrenceStrategyFactory.weekly(WeekdaySet.fromArray(['Mon', 'Wed']));
    const recurrence2 = RecurrenceStrategyFactory.weekly(WeekdaySet.fromArray(['Mon', 'Wed']));
    const recurrence3 = RecurrenceStrategyFactory.monthlyNthWeekday(MonthlyRecurrencePattern.create(1, 'Mon'));

    const a = new SeasonSchedule({
      startDate,
      timeOfDay,
      timezone,
      recurrence: recurrence1,
      plannedRounds: 10,
    });

    const b = new SeasonSchedule({
      startDate,
      timeOfDay,
      timezone,
      recurrence: recurrence2,
      plannedRounds: 10,
    });

    const c = new SeasonSchedule({
      startDate,
      timeOfDay,
      timezone,
      recurrence: recurrence3,
      plannedRounds: 10,
    });

    expect(a.equals(b)).toBe(true);
    expect(a.equals(c)).toBe(false);
  });
});