/**
 * Name uniqueness for datasets (spec §05 → Naming & Uniqueness;
 * docs/architecture/07 §2).
 *
 * Portable core: no browser APIs, no React, no store access — plain data in,
 * plain data out. Dataset names are the key snippets reference via
 * `datasetRefs` and the contract a Vega-Lite spec uses through
 * `{ "data": { "name": "..." } }`, so they must be unique. Comparisons are
 * **case-insensitive** throughout (`Sales` and `sales` collide) so a single
 * display name maps to a single dataset regardless of how a reference is typed.
 *
 *   - `isNameTaken` — reject duplicate create/rename in the UI. `excludeId` lets
 *     a rename ignore the record being renamed (renaming `Sales` to `Sales`, or a
 *     case-only edit, is not a self-collision).
 *   - `makeUniqueName` — for non-interactive paths (import, extract, build chart)
 *     where blocking the user is worse than a silent, reported rename: derive the
 *     next free `${base} ${n}` (n ≥ 2). We never parse meaning out of a name; a
 *     base already ending in a number still just gets a suffix (`Q1 2024 2`).
 */

/** Case-insensitive: is `desired` already used by another dataset (minus `excludeId`)? */
export function isNameTaken(
  desired: string,
  datasets: ReadonlyArray<{ id: number; name: string }>,
  excludeId?: number,
): boolean {
  const lower = desired.trim().toLowerCase();
  return datasets.some((d) => d.id !== excludeId && d.name.toLowerCase() === lower);
}

/**
 * Returns `desired` (trimmed) if free, else the first available `${desired} ${n}`
 * (n ≥ 2). `existingNames` is the set of names already in the collection.
 * Comparison is case-insensitive; the returned name preserves `desired`'s casing.
 */
export function makeUniqueName(desired: string, existingNames: Iterable<string>): string {
  const taken = new Set<string>();
  for (const n of existingNames) taken.add(n.toLowerCase());

  const base = desired.trim();
  if (!taken.has(base.toLowerCase())) return base;

  let n = 2;
  while (taken.has(`${base} ${n}`.toLowerCase())) n++;
  return `${base} ${n}`;
}
