import { League } from '@core/racing/domain/entities/League';
import { Race } from '@core/racing/domain/entities/Race';
import { Track } from '@core/racing/domain/entities/Track';
import { seedId } from './SeedIdHelper';

export class RacingRaceFactory {
  constructor(
    private readonly baseDate: Date,
    private readonly persistence: 'postgres' | 'inmemory' = 'inmemory',
  ) {}

  create(leagues: League[], tracks: Track[]): Race[] {
    const cars = ['GT3 – Porsche 911', 'GT3 – BMW M4', 'LMP3 Prototype', 'GT4 – Alpine', 'Touring – Civic'];

    const leagueIds = leagues.map((l) => l.id.toString());
    const trackIds = tracks.map((t) => t.id);
    const demoLeagueId = 'league-5';

    const races: Race[] = [];

    // Create races with systematic coverage of different statuses and scenarios

    for (let i = 1; i <= 500; i++) {
      const leagueId = leagueIds[(i - 1) % leagueIds.length] ?? demoLeagueId;
      const trackId = trackIds[(i - 1) % trackIds.length]!;
      const track = tracks.find(t => t.id === trackId)!;

      // Determine status systematically to ensure good coverage
      let status: 'scheduled' | 'running' | 'completed' | 'cancelled';
      let scheduledAt: Date;

      // Use modulo to create a balanced distribution across 500 races
      const statusMod = i % 20; // 20 different patterns
      
      if (statusMod === 1 || statusMod === 2 || statusMod === 3) {
        // 15% running (3 out of 20)
        status = 'running';
        scheduledAt = this.addDays(this.baseDate, -1 + (statusMod * 0.5)); // Recent past/current
      } else if (statusMod === 4 || statusMod === 5 || statusMod === 6 || statusMod === 7) {
        // 20% cancelled (4 out of 20)
        status = 'cancelled';
        scheduledAt = this.addDays(this.baseDate, -30 + (statusMod * 2));
      } else if (statusMod === 8 || statusMod === 9 || statusMod === 10 || statusMod === 11 || statusMod === 12) {
        // 25% completed (5 out of 20)
        status = 'completed';
        scheduledAt = this.addDays(this.baseDate, -50 + (statusMod * 3));
      } else {
        // 40% scheduled (8 out of 20)
        status = 'scheduled';
        scheduledAt = this.addDays(this.baseDate, 1 + ((statusMod - 13) * 2));
      }

      const base = {
        id: seedId(`race-${i}`, this.persistence),
        leagueId,
        scheduledAt,
        track: track.name.toString(),
        trackId: track.id,
        car: cars[(i - 1) % cars.length]!,
      };

      // Create race based on status with appropriate data
      if (status === 'running') {
        races.push(
          Race.create({
            ...base,
            status: 'running',
            strengthOfField: 40 + (i % 60), // Valid SOF: 0-100
            registeredCount: 10 + (i % 15), // Varying registration counts
            maxParticipants: 20 + (i % 8), // 20-28 participants
          }),
        );
      } else if (status === 'completed') {
        races.push(
          Race.create({
            ...base,
            status: 'completed',
            strengthOfField: 30 + (i % 70), // Valid SOF: 0-100
            registeredCount: 6 + (i % 12),
            maxParticipants: 16 + (i % 10),
          }),
        );
      } else if (status === 'scheduled') {
        const hasRegistrations = i % 3 !== 0; // 66% have registrations
        races.push(
          Race.create({
            ...base,
            status: 'scheduled',
            ...(hasRegistrations && {
              strengthOfField: 35 + (i % 65), // Valid SOF: 0-100
              registeredCount: 4 + (i % 12),
              maxParticipants: 14 + (i % 12),
            }),
          }),
        );
      } else if (status === 'cancelled') {
        races.push(
          Race.create({
            ...base,
            status: 'cancelled',
          }),
        );
      }
    }

    return races;
  }

  private addDays(date: Date, days: number): Date {
    return new Date(date.getTime() + days * 24 * 60 * 60 * 1000);
  }
}