import { describe, it, expect } from 'vitest';
import { createRng } from '../rng';

describe('createRng (mulberry32)', () => {
    it('одинаковый seed — одинаковая последовательность', () => {
        const a = createRng(12345);
        const b = createRng(12345);
        for (let i = 0; i < 100; i++) {
            expect(a.next()).toBe(b.next());
        }
    });

    it('разные seed — разные последовательности', () => {
        const a = createRng(1);
        const b = createRng(2);
        const seqA = Array.from({ length: 10 }, () => a.next());
        const seqB = Array.from({ length: 10 }, () => b.next());
        expect(seqA).not.toEqual(seqB);
    });

    it('next в диапазоне 0..1', () => {
        const rng = createRng(42);
        for (let i = 0; i < 1000; i++) {
            const v = rng.next();
            expect(v).toBeGreaterThanOrEqual(0);
            expect(v).toBeLessThan(1);
        }
    });

    it('int внутри [min, max] включительно', () => {
        const rng = createRng(7);
        for (let i = 0; i < 500; i++) {
            const v = rng.int(2, 5);
            expect(v).toBeGreaterThanOrEqual(2);
            expect(v).toBeLessThanOrEqual(5);
            expect(Number.isInteger(v)).toBe(true);
        }
    });

    it('int достигает обоих концов диапазона', () => {
        const rng = createRng(9);
        const seen = new Set<number>();
        for (let i = 0; i < 500; i++) seen.add(rng.int(1, 3));
        expect(seen.has(1)).toBe(true);
        expect(seen.has(3)).toBe(true);
    });

    it('pick берёт элемент из массива', () => {
        const rng = createRng(3);
        const arr = ['a', 'b', 'c'] as const;
        for (let i = 0; i < 50; i++) {
            expect(arr).toContain(rng.pick(arr));
        }
    });

    it('pick из пустого массива бросает', () => {
        const rng = createRng(3);
        expect(() => rng.pick([])).toThrow();
    });

    it('chance(0) всегда false, chance(1) всегда true', () => {
        const rng = createRng(11);
        for (let i = 0; i < 100; i++) {
            expect(rng.chance(0)).toBe(false);
            expect(rng.chance(1)).toBe(true);
        }
    });

    it('state() отражает позицию в последовательности (для сейва в связке с seed)', () => {
        const a = createRng(777);
        a.next();
        const s1 = a.state();
        a.next();
        const s2 = a.state();
        expect(s2).not.toBe(s1);

        // тот же seed и те же два вызова дают то же состояние
        const b = createRng(777);
        b.next();
        b.next();
        expect(b.state()).toBe(s2);
    });
});