import constants from '@tunarr/shared/constants';
import type { TimeSlotSchedule } from '@tunarr/types/api';
import { maxBy, minBy } from 'lodash-es';
import { describe, expect, test } from 'vitest';
import { createFakeProgramOrm } from '../../testing/fakes/entityCreators.ts';
import { groupByUniq } from '../../util/index.ts';
import type { SlotSchedulerProgram } from './slotSchedulerUtil.js';
import { scheduleTimeSlots } from './TimeSlotService.ts';

describe('TimeSlotService', () => {
  describe('scheduleTimeSlots', () => {
    describe('basic functionality', () => {
      test('successfully creates a schedule without errors', async () => {
        // Start with a very simple test that just verifies the function runs
        const programs: SlotSchedulerProgram[] = [];

        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 1,
          padMs: 30 * 60 * 1000, // 30 min slots
          slots: [
            {
              startTime: 0,
              type: 'movie',
              order: 'next',
              direction: 'asc',
            },
          ],
          period: 'day',
          latenessMs: 0,
          timeZoneOffset: 0,
        };

        const result = await scheduleTimeSlots(schedule, programs);

        expect(result.lineup).toBeDefined();
        expect(result.startTime).toBeGreaterThan(0);
      });

      test('schedules movie programs correctly', async () => {
        const programs: SlotSchedulerProgram[] = [
          {
            ...createFakeProgramOrm({
              uuid: 'movie1',
              title: 'Movie 1',
              type: 'movie',
              duration: 120 * 60 * 1000, // 2 hours
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          },
          {
            ...createFakeProgramOrm({
              uuid: 'movie2',
              title: 'Movie 2',
              type: 'movie',
              duration: 90 * 60 * 1000, // 90 minutes
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          },
        ];

        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 1,
          padMs: 120 * 60 * 1000, // 2 hour slots
          slots: [
            {
              startTime: 0,
              type: 'movie',
              order: 'next',
              direction: 'asc',
            },
          ],
          period: 'day',
          latenessMs: 0,
          timeZoneOffset: 0,
        };

        const result = await scheduleTimeSlots(schedule, programs);

        expect(result.lineup).toBeDefined();
        expect(result.lineup.length).toBeGreaterThan(0);
      });

      test('handles empty program list', async () => {
        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 1,
          padMs: 30 * 60 * 1000,
          slots: [
            {
              startTime: 0,
              type: 'movie',
              order: 'next',
              direction: 'asc',
            },
          ],
          period: 'day',
          latenessMs: 0,
          timeZoneOffset: 0,
        };

        const result = await scheduleTimeSlots(schedule, []);

        expect(result.lineup).toBeDefined();
        // Empty program list may result in flex time
        expect(result.lineup.length).toBeGreaterThanOrEqual(0);
      });

      test('schedules multiple slots in a day period', async () => {
        const programs: SlotSchedulerProgram[] = [
          {
            ...createFakeProgramOrm({
              uuid: 'show1-ep1',
              title: 'Show 1 - Episode 1',
              type: 'episode',
              duration: 30 * 60 * 1000,
              tvShowUuid: 'show1',
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          },
          {
            ...createFakeProgramOrm({
              uuid: 'movie1',
              title: 'Movie 1',
              type: 'movie',
              duration: 120 * 60 * 1000, // 2 hours
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          },
        ];

        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 1,
          padMs: 60 * 60 * 1000, // 1 hour slots
          slots: [
            {
              startTime: 0, // Midnight
              type: 'show',
              showId: 'show1',
              order: 'next',
              direction: 'asc',
              seasonFilter: [],
            },
            {
              startTime: 12 * 60 * 60 * 1000, // Noon
              type: 'movie',
              order: 'next',
              direction: 'asc',
            },
          ],
          period: 'day',
          latenessMs: 0,
          timeZoneOffset: 0,
        };

        const result = await scheduleTimeSlots(schedule, programs);

        expect(result.lineup).toBeDefined();
        expect(result.lineup.length).toBeGreaterThan(0);
        // Should have both show episodes and movies
        // Content programs are condensed and don't have subtype
        // We just check that we have content programs scheduled
        const hasContent = result.lineup.some((p) => p.type === 'content');
        expect(hasContent).toBe(true);
      });
    });

    describe('padding and alignment', () => {
      test('respects padMs for slot boundaries', async () => {
        const programs: SlotSchedulerProgram[] = [
          {
            ...createFakeProgramOrm({
              uuid: 'show1-ep1',
              type: 'episode',
              duration: 25 * 60 * 1000, // 25 minutes - doesn't fit evenly
              tvShowUuid: 'show1',
              show: {
                uuid: 'show1',
              },
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          },
        ];

        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 1,
          padMs: 30 * 60 * 1000, // 30 min slots
          slots: [
            {
              startTime: 0,
              type: 'show',
              showId: 'show1',
              order: 'next',
              direction: 'asc',
              seasonFilter: [],
            },
          ],
          period: 'day',
          latenessMs: 0,
          timeZoneOffset: 0,
        };

        const result = await scheduleTimeSlots(schedule, programs);

        expect(result.lineup).toBeDefined();
        // Should add flex time to align to slot boundaries
        const hasFlexTime = result.lineup.some((p) => p.type === 'flex');
        expect(hasFlexTime).toBe(true);

        let t = result.startTime;
        for (const item of result.lineup) {
          if (item.type !== 'content') {
            t += item.duration;
            continue;
          }

          // Content always starts on the 30m mark.
          expect(t % (30 * 60 * 1000)).toBe(0);
          t += item.duration;
        }
      });

      test('handles SLACK constant correctly', async () => {
        // SLACK = 300ms according to constants
        const programs: SlotSchedulerProgram[] = [
          {
            ...createFakeProgramOrm({
              uuid: 'show1-ep1',
              type: 'episode',
              // Duration that's almost aligned but within SLACK
              duration: 30 * 60 * 1000 - constants.SLACK / 2,
              tvShowUuid: 'show1',
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          },
        ];

        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 1,
          padMs: 30 * 60 * 1000,
          slots: [
            {
              startTime: 0,
              type: 'show',
              showId: 'show1',
              order: 'next',
              direction: 'asc',
              seasonFilter: [],
            },
          ],
          period: 'day',
          latenessMs: 0,
          timeZoneOffset: 0,
        };

        const result = await scheduleTimeSlots(schedule, programs);

        expect(result.lineup).toBeDefined();
        // The schedule should handle near-alignment gracefully
      });
    });

    describe('program iteration order', () => {
      test('respects "next" order with "asc" direction', async () => {
        const programs: SlotSchedulerProgram[] = Array.from(
          { length: 5 },
          (_, i) => ({
            ...createFakeProgramOrm({
              uuid: `show1-ep${i + 1}`,
              title: `Episode ${i + 1}`,
              type: 'episode',
              duration: 30 * 60 * 1000,
              episode: i + 1,
              tvShowUuid: 'show1',
              show: {
                uuid: 'show1',
              },
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          }),
        );

        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 1,
          padMs: 30 * 60 * 1000,
          slots: [
            {
              startTime: 0,
              type: 'show',
              showId: 'show1',
              order: 'next',
              direction: 'asc',
              seasonFilter: [],
            },
          ],
          period: 'day',
          latenessMs: 0,
          timeZoneOffset: 0,
        };

        const programsById = groupByUniq(programs, (p) => p.uuid);

        const result = await scheduleTimeSlots(schedule, programs);

        expect(result.lineup).toBeDefined();
        // Note: CondensedChannelProgram doesn't expose episode details
        // We can only verify that content programs were scheduled
        const contentPrograms = result.lineup.filter(
          (p) => p.type === 'content',
        );
        expect(contentPrograms.length).toBeGreaterThan(0);

        const maxEpNumber = maxBy(programs, (p) => p.episode)?.episode!;
        const minEpNumber = minBy(programs, (p) => p.episode)?.episode!;

        for (let i = 0; i < contentPrograms.length; i++) {
          if (i === contentPrograms.length - 1) {
            continue;
          }

          expect(contentPrograms[i].id).toBeDefined();
          expect(contentPrograms[i + 1].id).toBeDefined();
          const curr = programsById[contentPrograms[i].id!];
          const next = programsById[contentPrograms[i + 1].id!];

          expect(curr.episode).toBeDefined();

          // Account for loops
          if (curr.episode === maxEpNumber) {
            expect(next.episode).toBe(minEpNumber);
          } else {
            expect(curr.episode).toBeLessThan(next.episode!);
          }
        }
      });

      test('respects "next" order with "desc" direction', async () => {
        const programs: SlotSchedulerProgram[] = Array.from(
          { length: 5 },
          (_, i) => ({
            ...createFakeProgramOrm({
              uuid: `show1-ep${i + 1}`,
              title: `Episode ${i + 1}`,
              type: 'episode',
              duration: 30 * 60 * 1000,
              episode: i + 1,
              tvShowUuid: 'show1',
              show: {
                uuid: 'show1',
              },
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          }),
        );

        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 1,
          padMs: 30 * 60 * 1000,
          slots: [
            {
              startTime: 0,
              type: 'show',
              showId: 'show1',
              order: 'next',
              direction: 'desc',
              seasonFilter: [],
            },
          ],
          period: 'day',
          latenessMs: 0,
          timeZoneOffset: 0,
        };

        const programsById = groupByUniq(programs, (p) => p.uuid);

        const result = await scheduleTimeSlots(schedule, programs);

        expect(result.lineup).toBeDefined();
        // Note: CondensedChannelProgram doesn't expose episode details
        // We can only verify that content programs were scheduled
        const contentPrograms = result.lineup.filter(
          (p) => p.type === 'content',
        );
        expect(contentPrograms.length).toBeGreaterThan(0);

        const maxEpNumber = maxBy(programs, (p) => p.episode)?.episode!;
        const minEpNumber = minBy(programs, (p) => p.episode)?.episode!;

        for (let i = 0; i < contentPrograms.length; i++) {
          if (i === contentPrograms.length - 1) {
            continue;
          }

          expect(contentPrograms[i].id).toBeDefined();
          expect(contentPrograms[i + 1].id).toBeDefined();
          const curr = programsById[contentPrograms[i].id!];
          const next = programsById[contentPrograms[i + 1].id!];

          expect(curr.episode).toBeDefined();

          // Account for loops
          if (curr.episode === minEpNumber) {
            expect(next.episode).toBe(maxEpNumber);
          } else {
            expect(curr.episode).toBeGreaterThan(next.episode!);
          }
        }
      });

      test('handles "shuffle" order correctly', async () => {
        const programs: SlotSchedulerProgram[] = Array.from(
          { length: 10 },
          (_, i) => ({
            ...createFakeProgramOrm({
              uuid: `movie${i}`,
              title: `Movie ${i}`,
              type: 'movie',
              duration: 90 * 60 * 1000,
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          }),
        );

        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 2,
          padMs: 120 * 60 * 1000, // 2 hour slots
          slots: [
            {
              startTime: 0,
              type: 'movie',
              order: 'shuffle',
              direction: 'asc',
            },
          ],
          period: 'day',
          latenessMs: 0,
          timeZoneOffset: 0,
        };

        const seed = [1, 2, 3, 4]; // Fixed seed for reproducibility
        const result1 = await scheduleTimeSlots(schedule, programs, seed);
        const result2 = await scheduleTimeSlots(schedule, programs, seed);
      });
    });

    describe('flex time handling', () => {
      test('distributes flex time when flexPreference is "distribute"', async () => {
        const programs: SlotSchedulerProgram[] = [
          {
            ...createFakeProgramOrm({
              uuid: 'short-show',
              type: 'episode',
              duration: 22 * 60 * 1000, // 22 minutes
              tvShowUuid: 'show1',
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          },
        ];

        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 1,
          padMs: 30 * 60 * 1000, // 30 min slots
          slots: [
            {
              startTime: 0,
              type: 'show',
              showId: 'show1',
              order: 'next',
              direction: 'asc',
              seasonFilter: [],
            },
          ],
          period: 'day',
          latenessMs: 0,
          timeZoneOffset: 0,
        };

        const result = await scheduleTimeSlots(schedule, programs);

        expect(result.lineup).toBeDefined();
        // Should have flex programs to fill gaps
        const flexPrograms = result.lineup.filter((p) => p.type === 'flex');
        expect(flexPrograms.length).toBeGreaterThan(0);
        // Flex duration should make up the difference
        const flexTotal = flexPrograms.reduce((sum, p) => sum + p.duration, 0);
        expect(flexTotal).toBeGreaterThan(0);
      });

      test('extends existing flex program instead of creating new one', async () => {
        const programs: SlotSchedulerProgram[] = [
          {
            ...createFakeProgramOrm({
              uuid: 'short1',
              type: 'episode',
              duration: 20 * 60 * 1000, // 20 minutes
              tvShowUuid: 'show1',
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          },
          {
            ...createFakeProgramOrm({
              uuid: 'short2',
              type: 'episode',
              duration: 20 * 60 * 1000, // 20 minutes
              tvShowUuid: 'show1',
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          },
        ];

        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 1,
          padMs: 30 * 60 * 1000,
          slots: [
            {
              startTime: 0,
              type: 'show',
              showId: 'show1',
              order: 'next',
              direction: 'asc',
              seasonFilter: [],
            },
          ],
          period: 'day',
          latenessMs: 0,
          timeZoneOffset: 0,
        };

        const result = await scheduleTimeSlots(schedule, programs);

        expect(result.lineup).toBeDefined();
        // Check that consecutive flex programs are combined
        for (let i = 1; i < result.lineup.length; i++) {
          const prev = result.lineup[i - 1];
          const curr = result.lineup[i];
          // Should not have two flex programs in a row
          if (prev.type === 'flex') {
            expect(curr.type).not.toBe('flex');
          }
        }
      });
    });

    describe('multi-day scheduling', () => {
      test('schedules across multiple days', async () => {
        const programs: SlotSchedulerProgram[] = Array.from(
          { length: 20 },
          (_, i) => ({
            ...createFakeProgramOrm({
              uuid: `movie${i}`,
              type: 'movie',
              duration: 120 * 60 * 1000, // 2 hours
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          }),
        );

        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 3,
          padMs: 120 * 60 * 1000, // 2 hour slots
          slots: [
            {
              startTime: 0,
              type: 'movie',
              order: 'next',
              direction: 'asc',
            },
          ],
          period: 'day',
          latenessMs: 0,
          timeZoneOffset: 0,
        };

        const result = await scheduleTimeSlots(schedule, programs);

        expect(result.lineup).toBeDefined();
        const totalDuration = result.lineup.reduce(
          (sum, p) => sum + p.duration,
          0,
        );
        const threeDaysMs = 3 * 24 * 60 * 60 * 1000;
        // Should schedule approximately 3 days worth of content
        expect(totalDuration).toBeGreaterThan(0);
        expect(totalDuration).toBeLessThanOrEqual(
          threeDaysMs + 24 * 60 * 60 * 1000,
        ); // Allow some overflow
      });

      test('respects startTomorrow option', async () => {
        const programs: SlotSchedulerProgram[] = [
          {
            ...createFakeProgramOrm({
              uuid: 'movie1',
              type: 'movie',
              duration: 120 * 60 * 1000,
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          },
        ];

        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 1,
          padMs: 120 * 60 * 1000,
          slots: [
            {
              startTime: 0,
              type: 'movie',
              order: 'next',
              direction: 'asc',
            },
          ],
          period: 'day',
          latenessMs: 0,
          timeZoneOffset: 0,
          startTomorrow: true,
        };

        const result = await scheduleTimeSlots(schedule, programs);

        expect(result.lineup).toBeDefined();
        expect(result.lineup.length).toBeGreaterThan(0);
        // The schedule should start tomorrow
        // We can't easily verify the exact start time without mocking dayjs,
        // but we can verify the schedule was generated
      });
    });

    describe('period handling', () => {
      test('handles weekly period', async () => {
        const programs: SlotSchedulerProgram[] = [
          {
            ...createFakeProgramOrm({
              uuid: 'show1-ep1',
              type: 'episode',
              duration: 60 * 60 * 1000, // 1 hour
              tvShowUuid: 'show1',
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          },
        ];

        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 1,
          padMs: 60 * 60 * 1000,
          slots: [
            {
              startTime: 0,
              type: 'show',
              showId: 'show1',
              order: 'next',
              direction: 'asc',
              seasonFilter: [],
            },
          ],
          period: 'week',
          latenessMs: 0,
          timeZoneOffset: 0,
        };

        const result = await scheduleTimeSlots(schedule, programs);

        expect(result.lineup).toBeDefined();
        // Should handle weekly periods without errors
      });
    });

    describe('error handling', () => {
      test('handles slot without matching programs gracefully', async () => {
        const programs: SlotSchedulerProgram[] = [
          {
            ...createFakeProgramOrm({
              uuid: 'movie1',
              type: 'movie',
              duration: 120 * 60 * 1000,
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          },
        ];

        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 1,
          padMs: 60 * 60 * 1000,
          slots: [
            {
              startTime: 0,
              type: 'show',
              showId: 'nonexistent-show',
              order: 'next',
              direction: 'asc',
              seasonFilter: [],
            },
          ],
          period: 'day',
          latenessMs: 0,
          timeZoneOffset: 0,
        };

        const result = await scheduleTimeSlots(schedule, programs);

        // Should handle missing programs gracefully
        expect(result.lineup).toBeDefined();
        // May have flex time or may be empty
      });
    });

    describe('program deduplication', () => {
      test('deduplicates programs with same UUID', async () => {
        const baseProgram = createFakeProgramOrm({
          uuid: 'duplicate-uuid',
          type: 'movie',
          duration: 120 * 60 * 1000,
        });

        const programs: SlotSchedulerProgram[] = [
          {
            ...baseProgram,
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          },
          {
            ...baseProgram,
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          },
          {
            ...baseProgram,
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          },
        ];

        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 1,
          padMs: 120 * 60 * 1000,
          slots: [
            {
              startTime: 0,
              type: 'movie',
              order: 'next',
              direction: 'asc',
            },
          ],
          period: 'day',
          latenessMs: 0,
          timeZoneOffset: 0,
        };

        const result = await scheduleTimeSlots(schedule, programs);

        expect(result.lineup).toBeDefined();
        // Note: CondensedChannelProgram doesn't expose uuid for content programs
        // We can only verify the schedule was created
        expect(result.lineup.length).toBeGreaterThanOrEqual(0);
      });
    });

    describe('seed and reproducibility', () => {
      test('same seed produces identical schedules', async () => {
        const programs: SlotSchedulerProgram[] = Array.from(
          { length: 10 },
          (_, i) => ({
            ...createFakeProgramOrm({
              uuid: `movie${i}`,
              type: 'movie',
              duration: 90 * 60 * 1000,
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          }),
        );

        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 2,
          padMs: 120 * 60 * 1000,
          slots: [
            {
              startTime: 0,
              type: 'movie',
              order: 'shuffle',
              direction: 'asc',
            },
          ],
          period: 'day',
          latenessMs: 0,
          timeZoneOffset: 0,
        };

        const seed = [42, 123, 456, 789];
        const result1 = await scheduleTimeSlots(schedule, programs, seed);
        const result2 = await scheduleTimeSlots(schedule, programs, seed);

        expect(result1).toEqual(result2);
      });

      test('different seeds produce different schedules', async () => {
        const programs: SlotSchedulerProgram[] = Array.from(
          { length: 10 },
          (_, i) => ({
            ...createFakeProgramOrm({
              uuid: `movie${i}`,
              type: 'movie',
              duration: 90 * 60 * 1000,
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          }),
        );

        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 2,
          padMs: 120 * 60 * 1000,
          slots: [
            {
              startTime: 0,
              type: 'movie',
              order: 'shuffle',
              direction: 'asc',
            },
          ],
          period: 'day',
          latenessMs: 0,
          timeZoneOffset: 0,
        };

        const result1 = await scheduleTimeSlots(
          schedule,
          programs,
          [42, 123, 456, 789],
        );
        const result2 = await scheduleTimeSlots(
          schedule,
          programs,
          [99, 88, 77, 66],
        );

        // The results should be different (though theoretically could be same by chance)
        // At minimum, both should be successful
      });

      test('discardCount parameter affects randomization', async () => {
        const programs: SlotSchedulerProgram[] = Array.from(
          { length: 10 },
          (_, i) => ({
            ...createFakeProgramOrm({
              uuid: `movie${i}`,
              type: 'movie',
              duration: 90 * 60 * 1000,
            }),
            parentFillerLists: [],
            parentCustomShows: [],
            parentSmartCollections: [],
          }),
        );

        const schedule: TimeSlotSchedule = {
          type: 'time',
          flexPreference: 'distribute',
          maxDays: 2,
          padMs: 120 * 60 * 1000,
          slots: [
            {
              startTime: 0,
              type: 'movie',
              order: 'shuffle',
              direction: 'asc',
            },
          ],
          period: 'day',
          latenessMs: 0,
          timeZoneOffset: 0,
        };

        const seed = [42, 123, 456, 789];
        const result1 = await scheduleTimeSlots(schedule, programs, seed, 0);
        const result2 = await scheduleTimeSlots(schedule, programs, seed, 100);
      });
    });
  });
});
