/**
 * Seeded, deterministic pseudo-randomness.
 *
 * Every generator derives its seed from the store id and the metric name, so
 * the same request always returns the same numbers. That matters more than it
 * sounds: when the whole point of this phase is judging a design, numbers that
 * reshuffle on every reload make it impossible to tell a layout change from a
 * data change — and it keeps screenshots stable.
 */

export function hashSeed(...parts: (string | number)[]): number {
  let h = 2166136261;
  for (const part of parts) {
    const s = String(part);
    for (let i = 0; i < s.length; i++) {
      h ^= s.charCodeAt(i);
      h = Math.imul(h, 16777619);
    }
  }
  return h >>> 0;
}

/** mulberry32 — small, fast, good enough for fixtures. */
export function mulberry32(seed: number): () => number {
  let a = seed;
  return function next() {
    a |= 0;
    a = (a + 0x6d2b79f5) | 0;
    let t = Math.imul(a ^ (a >>> 15), 1 | a);
    t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  };
}

export function createRng(...parts: (string | number)[]) {
  const next = mulberry32(hashSeed(...parts));
  return {
    next,
    /** Integer in [min, max]. */
    int: (min: number, max: number) =>
      Math.floor(next() * (max - min + 1)) + min,
    /** Float in [min, max). */
    float: (min: number, max: number) => next() * (max - min) + min,
    pick: <T>(arr: readonly T[]): T => arr[Math.floor(next() * arr.length)],
  };
}
