import 'package:block_seasons/core/rng.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  group('SeededRng', () {
    test('same seed produces identical 1000-draw sequence', () {
      final a = SeededRng(8841273);
      final b = SeededRng(8841273);
      for (var i = 0; i < 1000; i++) {
        expect(a.nextInt(1 << 30), b.nextInt(1 << 30));
      }
    });

    test('different seeds produce different sequences', () {
      final a = SeededRng(1);
      final b = SeededRng(2);
      final drawsA = List.generate(20, (_) => a.nextInt(1 << 30));
      final drawsB = List.generate(20, (_) => b.nextInt(1 << 30));
      expect(drawsA, isNot(equals(drawsB)));
    });

    test('nextInt stays within [0, max)', () {
      final rng = SeededRng(42);
      for (final max in [1, 2, 3, 7, 40, 1000]) {
        for (var i = 0; i < 2000; i++) {
          final v = rng.nextInt(max);
          expect(v, inInclusiveRange(0, max - 1));
        }
      }
    });

    test('nextInt eventually covers every value for small max', () {
      final rng = SeededRng(7);
      final seen = <int>{};
      for (var i = 0; i < 1000; i++) {
        seen.add(rng.nextInt(6));
      }
      expect(seen, {0, 1, 2, 3, 4, 5});
    });

    test('nextDouble stays within [0, 1)', () {
      final rng = SeededRng(99);
      for (var i = 0; i < 5000; i++) {
        final v = rng.nextDouble();
        expect(v, greaterThanOrEqualTo(0.0));
        expect(v, lessThan(1.0));
      }
    });

    test('fork creates an independent stream that is deterministic', () {
      final a = SeededRng(123).fork(5);
      final b = SeededRng(123).fork(5);
      final c = SeededRng(123).fork(6);
      final drawsA = List.generate(20, (_) => a.nextInt(1 << 30));
      final drawsB = List.generate(20, (_) => b.nextInt(1 << 30));
      final drawsC = List.generate(20, (_) => c.nextInt(1 << 30));
      expect(drawsA, drawsB);
      expect(drawsA, isNot(equals(drawsC)));
    });
  });
}
