// ─── Guardian Name Determinism Test ───────────────────────────────────────────
// Regression test for #161: Guardian names must be deterministic per floor.
// Names derived from Math.random() would change on every call.

import { describe, it, expect } from 'vitest';
import {
  generateGuardianName,
  getGuardianForFloor,
  getAllGuardianFloors,
} from '../data/guardian-encounters';

describe('generateGuardianName', () => {
  it('should return the same name for the same elements and floor', () => {
    const name1 = generateGuardianName(['fire'], 90);
    const name2 = generateGuardianName(['fire'], 90);
    expect(name1).toBe(name2);
  });

  it('should return different names for different elements', () => {
    const nameFire = generateGuardianName(['fire'], 90);
    const nameWater = generateGuardianName(['water'], 90);
    expect(nameFire).not.toBe(nameWater);
  });

  it('should return different names for different floors', () => {
    const name90 = generateGuardianName(['fire'], 90);
    const name100 = generateGuardianName(['fire'], 100);
    expect(name90).not.toBe(name100);
  });

  it('should produce non-empty names', () => {
    const name = generateGuardianName(['metal'], 90);
    expect(name).toBeTruthy();
    expect(name.length).toBeGreaterThan(0);
  });

  it('should follow the "Prefix the Title" pattern for single element', () => {
    const name = generateGuardianName(['crystal'], 120);
    expect(name).toMatch(/^[\w]+ the [\w]+$/);
  });

  it('should combine prefixes with hyphen for multi-element', () => {
    const name = generateGuardianName(['fire', 'water'], 150);
    expect(name).toMatch(/^[\w]+-[\w]+ the [\w]+$/);
  });

  it('should produce "Unknown the <title>" for unknown element', () => {
    const name = generateGuardianName(['nonexistent'], 90);
    expect(name).toMatch(/^Unknown the [\w]+$/);
  });
});

describe('getGuardianForFloor', () => {
  it('should return stable names for composite guardians (floors 90-110)', () => {
    const g90a = getGuardianForFloor(90);
    const g90b = getGuardianForFloor(90);
    expect(g90a).not.toBeNull();
    expect(g90b).not.toBeNull();
    expect(g90a!.name).toBe(g90b!.name);

    const g100a = getGuardianForFloor(100);
    const g100b = getGuardianForFloor(100);
    expect(g100a!.name).toBe(g100b!.name);

    const g110a = getGuardianForFloor(110);
    const g110b = getGuardianForFloor(110);
    expect(g110a!.name).toBe(g110b!.name);
  });

  it('should return stable names for exotic guardians (floors 170-200)', () => {
    for (const floor of [170, 180, 190, 200]) {
      const a = getGuardianForFloor(floor);
      const b = getGuardianForFloor(floor);
      expect(a).not.toBeNull();
      expect(a!.name).toBe(b!.name);
    }
  });

  it('should preserve existing names for base guardians', () => {
    const g10 = getGuardianForFloor(10);
    expect(g10!.name).toBe('Ignis Prime');
  });

  it('should return different names for different floors', () => {
    const g90 = getGuardianForFloor(90);
    const g170 = getGuardianForFloor(170);
    expect(g90!.name).not.toBe(g170!.name);
  });

  it('should return arrays for element field', () => {
    const g10 = getGuardianForFloor(10);
    expect(Array.isArray(g10!.element)).toBe(true);
    expect(g10!.element).toContain('fire');
  });
});

describe('getAllGuardianFloors', () => {
  it('should include all static guardian floors', () => {
    const floors = getAllGuardianFloors();
    for (const f of [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 130, 140, 150, 160, 170, 180, 190, 200]) {
      expect(floors).toContain(f);
    }
  });

  it('should include procedural guardian floors 210-450', () => {
    const floors = getAllGuardianFloors();
    expect(floors).toContain(210);
    expect(floors).toContain(250);
    expect(floors).toContain(300);
    expect(floors).toContain(400);
    expect(floors).toContain(450);
  });

  it('should be sorted', () => {
    const floors = getAllGuardianFloors();
    for (let i = 1; i < floors.length; i++) {
      expect(floors[i]).toBeGreaterThan(floors[i - 1]);
    }
  });

  it('should produce unique names across many repeated calls', () => {
    const names = new Set<string>();
    for (let i = 0; i < 100; i++) {
      const g = getGuardianForFloor(90);
      names.add(g!.name);
    }
    expect(names.size).toBe(1);
  });
});
