import { describe, expect, it } from 'vitest';
import { shuffle, sample, pickInt } from '../random';

describe('shuffle', () => {
  it('returns a new array containing the same elements', () => {
    const input = [1, 2, 3, 4, 5];
    const out = shuffle(input);
    expect(out).not.toBe(input);
    expect([...out].sort()).toEqual([...input].sort());
    expect(input).toEqual([1, 2, 3, 4, 5]);
  });

  it('handles empty and single-element arrays', () => {
    expect(shuffle([])).toEqual([]);
    expect(shuffle([42])).toEqual([42]);
  });
});

describe('sample', () => {
  it('returns up to n unique elements from the source array', () => {
    const out = sample([1, 2, 3, 4, 5], 3);
    expect(out).toHaveLength(3);
    expect(new Set(out).size).toBe(3);
    for (const v of out) expect([1, 2, 3, 4, 5]).toContain(v);
  });

  it('returns the full shuffled array when n exceeds length', () => {
    const out = sample([1, 2, 3], 10);
    expect(out).toHaveLength(3);
    expect([...out].sort()).toEqual([1, 2, 3]);
  });

  it('returns an empty array when n is zero or negative', () => {
    expect(sample([1, 2, 3], 0)).toEqual([]);
    expect(sample([1, 2, 3], -2)).toEqual([]);
  });
});

describe('pickInt', () => {
  it('returns an integer in the inclusive range', () => {
    for (let i = 0; i < 100; i++) {
      const v = pickInt(2, 5);
      expect(Number.isInteger(v)).toBe(true);
      expect(v).toBeGreaterThanOrEqual(2);
      expect(v).toBeLessThanOrEqual(5);
    }
  });
});
