import { describe, it, expect } from 'vitest';
import {
  BUSY_SCENARIOS,
  selectRandomScenario,
  calculateBusyDelay,
  type BusyScenario,
} from './busy-scenarios.js';

describe('BUSY_SCENARIOS', () => {
  it('should have at least 4 predefined scenarios', () => {
    expect(BUSY_SCENARIOS.length).toBeGreaterThanOrEqual(4);
  });

  it('should have sport scenario with 25-45 min delay', () => {
    const sport = BUSY_SCENARIOS.find((s) => s.id === 'sport');
    expect(sport).toBeDefined();
    expect(sport!.delayMinutes.min).toBe(25);
    expect(sport!.delayMinutes.max).toBe(45);
  });

  it('should have shower scenario with 15-30 min delay', () => {
    const shower = BUSY_SCENARIOS.find((s) => s.id === 'shower');
    expect(shower).toBeDefined();
    expect(shower!.delayMinutes.min).toBe(15);
    expect(shower!.delayMinutes.max).toBe(30);
  });

  it('should have social scenario with 30-60 min delay', () => {
    const social = BUSY_SCENARIOS.find((s) => s.id === 'social');
    expect(social).toBeDefined();
    expect(social!.delayMinutes.min).toBe(30);
    expect(social!.delayMinutes.max).toBe(60);
  });

  it('should have sleep scenario with night time restriction', () => {
    const sleep = BUSY_SCENARIOS.find((s) => s.id === 'sleep');
    expect(sleep).toBeDefined();
    expect(sleep!.timeRestriction).toBeDefined();
    expect(sleep!.timeRestriction!.start).toBe(23);
    expect(sleep!.timeRestriction!.end).toBe(7);
  });

  it('should have Turkish messages for all scenarios', () => {
    for (const scenario of BUSY_SCENARIOS) {
      expect(scenario.message.length).toBeGreaterThan(0);
      expect(scenario.name.length).toBeGreaterThan(0);
    }
  });

  it('each scenario should have unique id', () => {
    const ids = BUSY_SCENARIOS.map((s) => s.id);
    expect(new Set(ids).size).toBe(ids.length);
  });
});

describe('selectRandomScenario', () => {
  it('should return a valid scenario for daytime hours', () => {
    const scenario = selectRandomScenario(14);
    expect(scenario).toBeDefined();
    expect(scenario.id).toBeTruthy();
    expect(scenario.message).toBeTruthy();
  });

  it('should not return sleep scenario during daytime', () => {
    // Run multiple times to increase confidence
    for (let i = 0; i < 50; i++) {
      const scenario = selectRandomScenario(14);
      expect(scenario.id).not.toBe('sleep');
    }
  });

  it('should return eligible scenarios during night hours', () => {
    const results = new Set<string>();
    for (let i = 0; i < 100; i++) {
      results.add(selectRandomScenario(2).id);
    }
    // Sleep should appear at night
    expect(results.has('sleep')).toBe(true);
  });

  it('should return a scenario for every hour of the day', () => {
    for (let hour = 0; hour < 24; hour++) {
      const scenario = selectRandomScenario(hour);
      expect(scenario).toBeDefined();
      expect(BUSY_SCENARIOS).toContain(scenario);
    }
  });
});

describe('calculateBusyDelay', () => {
  it('should return delay in seconds', () => {
    const scenario: BusyScenario = {
      id: 'test',
      name: 'Test',
      message: 'test',
      delayMinutes: { min: 10, max: 20 },
    };
    const delay = calculateBusyDelay(scenario);
    // min * 0.85 * 60 = 510, max * 1.15 * 60 = 1380
    expect(delay).toBeGreaterThanOrEqual(510);
    expect(delay).toBeLessThanOrEqual(1380);
  });

  it('should produce delays within extended range for sport scenario', () => {
    const sport = BUSY_SCENARIOS.find((s) => s.id === 'sport')!;
    for (let i = 0; i < 50; i++) {
      const delay = calculateBusyDelay(sport);
      // 25 * 0.85 * 60 = 1275, 45 * 1.15 * 60 = 3105
      expect(delay).toBeGreaterThanOrEqual(25 * 0.85 * 60);
      expect(delay).toBeLessThanOrEqual(45 * 1.15 * 60);
    }
  });

  it('should not always return the same value (has randomness)', () => {
    const scenario = BUSY_SCENARIOS[0];
    const results = new Set<number>();
    for (let i = 0; i < 20; i++) {
      results.add(calculateBusyDelay(scenario));
    }
    expect(results.size).toBeGreaterThan(1);
  });

  it('should return an integer (rounded seconds)', () => {
    const scenario = BUSY_SCENARIOS[0];
    for (let i = 0; i < 10; i++) {
      const delay = calculateBusyDelay(scenario);
      expect(Number.isInteger(delay)).toBe(true);
    }
  });
});
