import { describe, expect, it } from 'vitest';
import {
  HarnessAdapterUnavailableError,
  HarnessRegistrationError,
  HarnessRegistry,
} from './harness.registry.js';
import { FakeHarnessAdapter } from './testing/fake-harness.adapter.js';

describe('HarnessRegistry', () => {
  it('registers and looks up an adapter by harness id', () => {
    const registry = new HarnessRegistry();
    const adapter = new FakeHarnessAdapter({ id: 'fake' });

    registry.register(adapter);

    expect(registry.get('fake')).toBe(adapter);
    expect(registry.has('fake')).toBe(true);
    expect(registry.list().map((entry) => entry.id)).toEqual(['fake']);
  });

  it('rejects a blank adapter id', () => {
    const registry = new HarnessRegistry();

    let error: unknown;
    try {
      registry.register(new FakeHarnessAdapter({ id: '   ' }));
    } catch (caught) {
      error = caught;
    }

    expect(error).toBeInstanceOf(HarnessRegistrationError);
    expect((error as HarnessRegistrationError).reason).toBe('blank_id');
    expect(registry.list()).toEqual([]);
  });

  it('rejects a duplicate adapter id', () => {
    const registry = new HarnessRegistry();
    registry.register(new FakeHarnessAdapter({ id: 'fake' }));

    let error: unknown;
    try {
      registry.register(new FakeHarnessAdapter({ id: 'fake' }));
    } catch (caught) {
      error = caught;
    }

    expect(error).toBeInstanceOf(HarnessRegistrationError);
    expect((error as HarnessRegistrationError).reason).toBe('duplicate_id');
    expect((error as HarnessRegistrationError).harnessId).toBe('fake');
    // The original registration is untouched.
    expect(registry.list()).toHaveLength(1);
  });

  it('returns adapter_unavailable for an unknown harness id', () => {
    const registry = new HarnessRegistry();

    let error: unknown;
    try {
      registry.get('missing');
    } catch (caught) {
      error = caught;
    }

    expect(error).toBeInstanceOf(HarnessAdapterUnavailableError);
    expect((error as HarnessAdapterUnavailableError).code).toBe('adapter_unavailable');
    expect((error as HarnessAdapterUnavailableError).harnessId).toBe('missing');
    expect(registry.has('missing')).toBe(false);
  });
});
