// src/engine/remoting/TransportRegistry.ts

import type { ITransportAdapter } from './ITransportAdapter';
import type { ITransportRegistry } from './ITransportRegistry';

/**
 * Instance-based registry mapping scheme → ITransportAdapter.
 *
 * Expert Panel Decision (2024-12):
 * Converted from static singleton to instance-based for:
 * - Test isolation (each test gets own registry)
 * - Dependency injection (no ambient authority)
 * - Future distributed implementations
 *
 * Martin Fowler (PoEAA):
 *   "Registry pattern is fine. Global access is not."
 *
 * Mark Miller (Capability Security):
 *   "The registry is a capability. Pass it explicitly."
 *
 * Joe Armstrong (Erlang):
 *   "In Erlang, we'd pass the registry PID. No globals."
 */
export class TransportRegistry implements ITransportRegistry {
  private readonly adapters = new Map<string, ITransportAdapter>();

  register(scheme: string, adapter: ITransportAdapter): void {
    if (!scheme) throw new Error('[TransportRegistry] scheme is required');
    this.adapters.set(scheme.toLowerCase(), adapter);
  }

  unregister(scheme: string): void {
    this.adapters.delete(scheme.toLowerCase());
  }

  has(scheme: string): boolean {
    return this.adapters.has(scheme.toLowerCase());
  }

  resolveByScheme(scheme: string): ITransportAdapter {
    const adapter = this.adapters.get(scheme.toLowerCase());
    if (!adapter) {
      throw new Error(
        `[TransportRegistry] No transport adapter registered for scheme '${scheme}'`
      );
    }
    return adapter;
  }

  clear(): void {
    this.adapters.clear();
  }
}

// ═══════════════════════════════════════════════════════════════════════════
// BACKWARDS COMPATIBILITY SHIM (DEPRECATED)
// ═══════════════════════════════════════════════════════════════════════════
//
// These static methods provide backwards compatibility for existing code.
// They delegate to a module-level default instance.
//
// MIGRATION:
// - OLD: TransportRegistry.register('matrix', adapter);
// - NEW: runtime.transportRegistry.register('matrix', adapter);
//        OR create new TransportRegistry() for tests
//
// ═══════════════════════════════════════════════════════════════════════════

/**
 * Default instance for backwards compatibility.
 * Will be removed in future major version.
 *
 * @deprecated Use instance-based registry via runtime.transportRegistry
 */
const defaultRegistry = new TransportRegistry();

/**
 * Get the default registry instance.
 * For backwards compatibility during migration.
 *
 * @deprecated Inject TransportRegistry via runtime config instead
 */
export function getDefaultTransportRegistry(): TransportRegistry {
  return defaultRegistry;
}

/**
 * Reset the default registry (for testing).
 *
 * @deprecated Create new TransportRegistry() instances for tests
 */
export function resetDefaultTransportRegistry(): void {
  defaultRegistry.clear();
}

// ═══════════════════════════════════════════════════════════════════════════
// STATIC COMPATIBILITY LAYER
// ═══════════════════════════════════════════════════════════════════════════
//
// These re-export static methods that delegate to defaultRegistry.
// This allows existing code using TransportRegistry.register() to keep working.
//
// NOTE: We use namespace merging to add static methods to the class.
// ═══════════════════════════════════════════════════════════════════════════

// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace TransportRegistry {
  /** @deprecated Use instance method: new TransportRegistry().register() */
  export function register(scheme: string, adapter: ITransportAdapter): void {
    defaultRegistry.register(scheme, adapter);
  }

  /** @deprecated Use instance method */
  export function unregister(scheme: string): void {
    defaultRegistry.unregister(scheme);
  }

  /** @deprecated Use instance method */
  export function has(scheme: string): boolean {
    return defaultRegistry.has(scheme);
  }

  /** @deprecated Use instance method */
  export function resolveByScheme(scheme: string): ITransportAdapter {
    return defaultRegistry.resolveByScheme(scheme);
  }
}
