import { describe, it, expect } from 'vitest';
import { Bag } from './bag';
import { RULESETS } from './ruleset';
import { BLANK_INDEX } from '../alphabet';

describe('offline bag', () => {
  it('holds exactly the variant tile distribution', () => {
    const rs = RULESETS.scrabble_en;
    const total = rs.counts.reduce((a, b) => a + b, 0) + rs.blanks;
    const bag = new Bag('scrabble_en', 42);
    expect(bag.length).toBe(total);

    const drawn = bag.draw(total);
    expect(drawn.length).toBe(total);
    expect(bag.length).toBe(0);

    const tally = new Map<number, number>();
    for (const t of drawn) tally.set(t, (tally.get(t) ?? 0) + 1);
    for (let i = 0; i < rs.counts.length; i++) expect(tally.get(i) ?? 0).toBe(rs.counts[i]);
    expect(tally.get(BLANK_INDEX) ?? 0).toBe(rs.blanks);
  });

  it('draws beyond the remaining, returning all and emptying', () => {
    const bag = new Bag('scrabble_ru', 7);
    const total = bag.length;
    const all = bag.draw(total + 5);
    expect(all.length).toBe(total);
    expect(bag.length).toBe(0);
    expect(bag.draw(3)).toEqual([]);
  });

  it('returns tiles back to the bag', () => {
    const bag = new Bag('erudit_ru', 1);
    const before = bag.length;
    const seven = bag.draw(7);
    expect(bag.length).toBe(before - 7);
    bag.return(seven);
    expect(bag.length).toBe(before);
  });

  it('is deterministic for a given seed and operation sequence', () => {
    const a = new Bag('scrabble_en', 123);
    const b = new Bag('scrabble_en', 123);
    expect(a.draw(30)).toEqual(b.draw(30));
    // A return reshuffles both identically, so subsequent draws still agree.
    a.return([0, 1, 2]);
    b.return([0, 1, 2]);
    expect(a.draw(10)).toEqual(b.draw(10));
  });
});
