import type { SessionPersister } from './session-persister';

/**
 * Module-level registry of {@link SessionPersister}s keyed by session identity
 * string (GENC-1351 §5.10).
 *
 * A persister's lifetime is tied to the conversation session, not the DOM — like
 * the driver registry. The (up to two) element views that share a session (a
 * collapsed bubble + a popped-out panel) look up or create the ONE persister for
 * their key and delegate all restore-core persistence to it, so there is a single
 * save timer + carry-forward cache per session (no per-view double-writes/races).
 *
 * @internal
 */
const persisterRegistry = new Map<string, SessionPersister>();

/**
 * Returns the existing persister for `key`, or calls `factory` to create and
 * register a new one. First view to connect creates it; later views share it.
 */
export function getOrCreatePersister(
  key: string,
  factory: () => SessionPersister,
): SessionPersister {
  const existing = persisterRegistry.get(key);
  if (existing) return existing;
  const persister = factory();
  persisterRegistry.set(key, persister);
  return persister;
}

/** Returns the existing persister for `key`, or `undefined`. */
export function getPersister(key: string): SessionPersister | undefined {
  return persisterRegistry.get(key);
}

/**
 * Removes the persister for `key` (explicit session teardown). Disposes it first
 * so its debounced save AND diagnostics timers are cancelled — otherwise a timer
 * scheduled by the outgoing session fires after the in-place switch and flushes the
 * NEW session's entries under the OLD key, corrupting its stream (GENC-1351 §5.12).
 */
export function deletePersister(key: string): void {
  persisterRegistry.get(key)?.dispose();
  persisterRegistry.delete(key);
}

/**
 * Removes all entries. Exposed for test isolation only — not part of the public API.
 *
 * @internal
 */
export function clearPersisterRegistry(): void {
  persisterRegistry.clear();
}
