// Plugin Registry
// Manages registration and discovery of core banking system adapters

import { IPluginAdapter } from './generic-adapter';
import { TemenosAdapter } from './temenos-adapter';
import { FlexcubeAdapter } from './flexcube-adapter';
import { SwiftAdapter } from './swift-adapter';
import { Iso20022Adapter } from './iso20022-adapter';

export class PluginRegistry {
  private static instance: PluginRegistry;
  private adapters: Map<string, IPluginAdapter> = new Map();

  private constructor() {
    // Register built-in adapters
    this.registerBuiltInAdapters();
  }

  static getInstance(): PluginRegistry {
    if (!PluginRegistry.instance) {
      PluginRegistry.instance = new PluginRegistry();
    }
    return PluginRegistry.instance;
  }

  /**
   * Register built-in adapters
   */
  private registerBuiltInAdapters(): void {
    // Register Temenos adapter
    this.register('temenos', new TemenosAdapter());

    // Register Flexcube adapter
    this.register('flexcube', new FlexcubeAdapter());

    // Register SWIFT adapter
    this.register('swift', new SwiftAdapter());

    // Register ISO 20022 adapter
    this.register('iso20022', new Iso20022Adapter());
  }

  /**
   * Register a new adapter
   */
  register(name: string, adapter: IPluginAdapter): void {
    if (this.adapters.has(name)) {
      throw new Error(`Adapter with name '${name}' is already registered`);
    }

    this.adapters.set(name.toLowerCase(), adapter);
  }

  /**
   * Get adapter by name
   */
  get(name: string): IPluginAdapter | undefined {
    return this.adapters.get(name.toLowerCase());
  }

  /**
   * Get all registered adapters
   */
  getAll(): IPluginAdapter[] {
    return Array.from(this.adapters.values());
  }

  /**
   * Get list of adapter names
   */
  getNames(): string[] {
    return Array.from(this.adapters.keys());
  }

  /**
   * Check if adapter is registered
   */
  has(name: string): boolean {
    return this.adapters.has(name.toLowerCase());
  }

  /**
   * Unregister an adapter
   */
  unregister(name: string): boolean {
    return this.adapters.delete(name.toLowerCase());
  }

  /**
   * Get available adapters (those that are connected/available)
   */
  async getAvailableAdapters(): Promise<IPluginAdapter[]> {
    const available: IPluginAdapter[] = [];

    for (const adapter of this.adapters.values()) {
      try {
        if (await adapter.isAvailable()) {
          available.push(adapter);
        }
      } catch {
        // Skip unavailable adapters
      }
    }

    return available;
  }

  /**
   * Get adapter info
   */
  getAdapterInfo(name: string): { name: string; version: string; available: boolean } | null {
    const adapter = this.get(name);
    if (!adapter) {
      return null;
    }

    return {
      name: adapter.getName(),
      version: adapter.getVersion(),
      available: false, // Would need async check
    };
  }
}

// Export singleton instance
export const pluginRegistry = PluginRegistry.getInstance();

