let lastTimestamp = 0;
let sameTimestampSequence = 0;

export interface DedupeEntityIdsResult<T> {
  items: T[];
  changed: boolean;
}

export function createEntityId(prefix: string, timestamp = Date.now()): string {
  if (timestamp === lastTimestamp) {
    sameTimestampSequence += 1;
  } else {
    lastTimestamp = timestamp;
    sameTimestampSequence = 0;
  }
  return `${prefix}-${timestamp}-${sameTimestampSequence.toString(36)}`;
}

export function dedupeEntityIds<T extends { id: string }>(
  items: T[],
  prefix: string,
  timestamp = Date.now(),
): DedupeEntityIdsResult<T> {
  const seen = new Set<string>();
  let changed = false;

  const deduped = items.map((item) => {
    if (item.id && !seen.has(item.id)) {
      seen.add(item.id);
      return item;
    }

    changed = true;
    let nextId = createEntityId(prefix, timestamp);
    while (seen.has(nextId)) {
      nextId = createEntityId(prefix, timestamp);
    }
    seen.add(nextId);
    return { ...item, id: nextId };
  });

  return { items: changed ? deduped : items, changed };
}
