/**
 * Replay oracle (Bottom-Up hard gate: "replay the same fixture twice and prove
 * no duplicate business state"). Ingests a fixture, counts, ingests it AGAIN,
 * counts again. The caller asserts: same interaction id, unchanged count.
 *
 * The `ingest` function the caller supplies must derive its idempotency key
 * deterministically from the fixture (e.g. its providerEventId) so the second
 * run is a true duplicate.
 */
export interface ReplayResult {
  firstId: string;
  secondId: string;
  countAfterFirst: number;
  countAfterSecond: number;
}

export async function replayTwice<F>(
  fixture: F,
  ingest: (f: F) => Promise<{ interactionId: string }>,
  countInteractions: () => Promise<number>,
): Promise<ReplayResult> {
  const first = await ingest(fixture);
  const countAfterFirst = await countInteractions();
  const second = await ingest(fixture);
  const countAfterSecond = await countInteractions();
  return {
    firstId: first.interactionId,
    secondId: second.interactionId,
    countAfterFirst,
    countAfterSecond,
  };
}

/** Convenience predicate: true when a replay produced no new business state. */
export function isIdempotent(r: ReplayResult): boolean {
  return r.firstId === r.secondId && r.countAfterFirst === r.countAfterSecond;
}
