import { describe, expect, test } from 'vitest';
import { isNameTaken, makeUniqueName } from './naming';

describe('isNameTaken', () => {
  const datasets = [
    { id: 1, name: 'Sales' },
    { id: 2, name: 'Regions' },
  ];

  test('matches case-insensitively', () => {
    expect(isNameTaken('sales', datasets)).toBe(true);
    expect(isNameTaken('SALES', datasets)).toBe(true);
    expect(isNameTaken('Unknown', datasets)).toBe(false);
  });

  test('trims the desired name before comparing', () => {
    expect(isNameTaken('  Sales  ', datasets)).toBe(true);
  });

  test('excludeId lets a record ignore itself (e.g. a case-only rename)', () => {
    expect(isNameTaken('Sales', datasets, 1)).toBe(false);
    expect(isNameTaken('sales', datasets, 1)).toBe(false);
    // Renaming to a name owned by a *different* record is still taken.
    expect(isNameTaken('Regions', datasets, 1)).toBe(true);
  });
});

describe('makeUniqueName', () => {
  test('returns the trimmed desired name when free', () => {
    expect(makeUniqueName('Fresh', ['Sales'])).toBe('Fresh');
    expect(makeUniqueName('  Fresh  ', ['Sales'])).toBe('Fresh');
  });

  test('suffixes collisions: Name -> Name 2 -> Name 3', () => {
    expect(makeUniqueName('Name', ['Name'])).toBe('Name 2');
    expect(makeUniqueName('Name', ['Name', 'Name 2'])).toBe('Name 3');
  });

  test('comparison is case-insensitive but casing is preserved', () => {
    expect(makeUniqueName('Name', ['name'])).toBe('Name 2');
    expect(makeUniqueName('MyData', ['mydata'])).toBe('MyData 2');
  });

  test('within-batch reservation is the caller responsibility: a single call does not reserve', () => {
    // Two consecutive calls with the same existing set both yield "Name 2" —
    // the caller must reserve each chosen name as it goes (arch 07 §5).
    const existing = ['Name'];
    expect(makeUniqueName('Name', existing)).toBe('Name 2');
    expect(makeUniqueName('Name', existing)).toBe('Name 2');
    // Reserving manually advances to the next free slot.
    expect(makeUniqueName('Name', [...existing, 'Name 2'])).toBe('Name 3');
  });
});
