import type { RecipeSourceAdapter } from "./recipe-source-adapter.js";

/**
 * In-memory registry of every {@link RecipeSourceAdapter} (recipe-source-adapter.ts)
 * this process knows about, keyed by `adapter.key`. Deliberately not
 * DB-backed — an adapter *is* code (a website's fetch/parse logic can't
 * live in a database row) — but the `Source` table (schema.prisma) is kept
 * in sync with it (see `syncRecipeSources`, recipe-source-sync.ts) so a
 * saved `Recipe.sourceId` has a row to point at. Actually saving an
 * imported recipe (setting `Recipe.sourceId`/`externalId`) is still future
 * work for whichever module ends up driving the import pipeline — this
 * registry only answers "which sources can we import from right now".
 *
 * No adapter is registered here yet — this file only provides the
 * mechanism; `registerRecipeSource` is meant to be called once per adapter
 * module, at whatever point a concrete source is added.
 */
const adapters = new Map<string, RecipeSourceAdapter>();

/**
 * Registers `adapter` under its own `key`. Throws if that key is already
 * taken — two adapters silently overwriting each other would be a bug (a
 * caller reaching for "marmiton" should never get a different adapter than
 * the one it registered), not a case to swallow.
 */
export function registerRecipeSource<TRawDetail>(adapter: RecipeSourceAdapter<TRawDetail>): void {
  if (adapters.has(adapter.key)) {
    throw new Error(`Recipe source "${adapter.key}" is already registered`);
  }
  // `TRawDetail` only matters within one adapter's own list/fetchDetail/parse
  // trio — once stored, callers look adapters up by key and drive the same
  // three methods generically, so the registry itself doesn't need to know
  // each adapter's raw type. This cast is the standard way to store a
  // heterogeneous collection of otherwise-identically-shaped generics.
  adapters.set(adapter.key, adapter as RecipeSourceAdapter);
}

/** The adapter registered under `key`, or `undefined` if none is. */
export function getRecipeSource(key: string): RecipeSourceAdapter | undefined {
  return adapters.get(key);
}

/** Every registered adapter — e.g. to offer a source picker. */
export function listRecipeSources(): RecipeSourceAdapter[] {
  return [...adapters.values()];
}

/**
 * Empties the registry. Not meant for application code — `apps/api/src`
 * never calls this — only for test isolation, the same role
 * `test-support/reset-db.ts` plays for the database: without it, adapters
 * registered by one test file would leak into the next.
 */
export function clearRecipeSources(): void {
  adapters.clear();
}
