import type { ProviderAdapter } from "./ProviderAdapter";

/**
 * AdapterRegistry — runtime registry of ProviderAdapter instances.
 *
 * Register adapters at startup. The handler calls resolve(req) to pick
 * the right adapter for each inbound request.
 */
export class AdapterRegistry {
  private readonly adapters: ProviderAdapter[] = [];

  /**
   * Register an adapter. Throws if an adapter with the same id is already
   * registered (programming error — no silent overwrite).
   */
  register(adapter: ProviderAdapter): void {
    const existing = this.adapters.find((a) => a.id === adapter.id);
    if (existing) {
      throw new Error(
        `AdapterRegistry: duplicate adapter id "${adapter.id}" — already registered`
      );
    }
    this.adapters.push(adapter);
  }

  /**
   * Resolve the first registered adapter whose matches(req) returns true.
   * Returns null if no adapter matches (proxy will 502 or forward unchanged).
   */
  resolve(req: Request): ProviderAdapter | null {
    for (const adapter of this.adapters) {
      if (adapter.matches(req)) return adapter;
    }
    return null;
  }

  /**
   * Return a shallow copy of all registered adapters.
   */
  list(): ProviderAdapter[] {
    return [...this.adapters];
  }

  /** Return all registered adapter ids. */
  ids(): string[] {
    return this.adapters.map((a) => a.id);
  }

  /**
   * Like resolve() but throws if no adapter matches.
   * Useful in tests and when the caller has already verified the route.
   */
  lookup(req: Request): ProviderAdapter {
    const a = this.resolve(req);
    if (!a) throw new Error(`AdapterRegistry: no adapter matched ${req.url}`);
    return a;
  }
}
