import { assert, createLogicSuite } from '@genesislcap/foundation-testing';
import type { AiDriver } from '../components/ai-driver/ai-driver';
import {
  clearDriverRegistry,
  deleteDriver,
  getDriver,
  getDriverAgentsKey,
  getOrCreateDriver,
} from './driver-registry';

// Minimal stub — the registry only stores and returns the reference; it never
// invokes driver methods, so an opaque object is sufficient.
const stub = (id: string): AiDriver => ({ id }) as unknown as AiDriver;

const suite = createLogicSuite('driver-registry agents-key tracking');

suite('getOrCreateDriver creates once and records the agents key', () => {
  clearDriverRegistry();
  const d = stub('a');
  const created = getOrCreateDriver('k', 'agentsKeyA', () => d);
  assert.is(created, d);
  assert.is(getDriver('k'), d);
  assert.is(getDriverAgentsKey('k'), 'agentsKeyA');
});

suite('reuse returns the existing driver and keeps its original agents key', () => {
  clearDriverRegistry();
  const first = stub('first');
  getOrCreateDriver('k', 'agentsKeyA', () => first);
  // A second component sharing the key, even with a different desired agents
  // fingerprint, must NOT replace the driver or overwrite the recorded key.
  let factoryCalled = false;
  const reused = getOrCreateDriver('k', 'agentsKeyB', () => {
    factoryCalled = true;
    return stub('second');
  });
  assert.is(reused, first);
  assert.is(factoryCalled, false);
  assert.is(getDriverAgentsKey('k'), 'agentsKeyA');
});

suite('deleteDriver clears both the driver and its recorded agents key', () => {
  clearDriverRegistry();
  getOrCreateDriver('k', 'agentsKeyA', () => stub('a'));
  deleteDriver('k');
  assert.is(getDriver('k'), undefined);
  assert.is(getDriverAgentsKey('k'), undefined);
});

suite('a rebuild under the same key records the new agents key (the adopt signal)', () => {
  clearDriverRegistry();
  // Initial driver, built for the old agent set.
  getOrCreateDriver('k', 'old', () => stub('d-old'));
  // Rebuild: the host deletes then recreates with the new fingerprint.
  deleteDriver('k');
  const rebuilt = stub('d-new');
  getOrCreateDriver('k', 'new', () => rebuilt);
  // GENC-1388: a sibling sharing the key can now detect that the registry driver
  // already matches its desired agents and adopt `rebuilt`, rather than
  // recreating (which would orphan a driver mid-turn).
  assert.is(getDriver('k'), rebuilt);
  assert.is(getDriverAgentsKey('k'), 'new');
});

suite('getDriverAgentsKey is undefined for an unknown key', () => {
  clearDriverRegistry();
  assert.is(getDriverAgentsKey('missing'), undefined);
});

suite.run();
