/**
 * DNS Provider Registry
 * Manages available DNS provider adapters.
 * Providers register themselves, and the active provider is selected by config.
 */
const path = require('path');

class DNSProviderRegistry {
  constructor() {
    this.providers = new Map();    // providerId -> adapter class
    this.instances = new Map();    // providerId -> adapter instance
  }

  /** Register a provider adapter class */
  register(adapterClass) {
    const instance = new adapterClass({}, {});
    const id = instance.providerId;
    if (this.providers.has(id)) {
      console.warn(`DNS provider "${id}" already registered, overwriting`);
    }
    this.providers.set(id, adapterClass);
  }

  /** Get list of all registered provider IDs */
  getProviderIds() {
    return Array.from(this.providers.keys());
  }

  /** Get metadata for all providers (without instantiating with real config) */
  getProviderMeta() {
    return this.getProviderIds().map(id => {
      const Adapter = this.providers.get(id);
      const inst = new Adapter({}, {});
      return {
        id: inst.providerId,
        displayName: inst.displayName,
        capabilities: inst.getCapabilities()
      };
    });
  }

  /** 
   * Get or create an adapter instance for the given provider + config
   * @param {string} providerId - The provider to instantiate
   * @param {Object} config - Provider-specific configuration
   * @param {Object} ctx - Shared application context
   * @returns {BaseDNSProvider} The provider adapter instance
   */
  getProvider(providerId, config, ctx) {
    // Re-create if config changed
    const cacheKey = providerId;
    const Adapter = this.providers.get(providerId);
    if (!Adapter) {
      throw new Error(`Unknown DNS provider: ${providerId}. Available: ${this.getProviderIds().join(', ')}`);
    }
    const instance = new Adapter(config, ctx);
    this.instances.set(cacheKey, instance);
    return instance;
  }

  /** Auto-discover and register all providers in this directory */
  autoDiscover() {
    const fs = require('fs');
    const dir = __dirname;
    const files = fs.readdirSync(dir).filter(f => 
      f !== 'base.js' && f !== 'registry.js' && f.endsWith('.js') && !f.startsWith('.')
    );
    for (const file of files) {
      try {
        const Loaded = require(path.join(dir, file));
        // Support: module.exports = Class, module.exports = { Class }, or plain objects
        let cls = null;
        if (typeof Loaded === 'function') {
          cls = Loaded;
        } else if (typeof Loaded === 'object' && Loaded !== null) {
          // Try to find a class in the exported object
          cls = Object.values(Loaded).find(v => typeof v === 'function');
        }
        if (cls) {
          // Verify it has providerId (on prototype or set in constructor)
          try {
            const test = new cls({}, {});
            if (test.providerId && typeof test.getCapabilities === 'function') {
              this.register(cls);
            }
          } catch {
            // Not a valid provider adapter, skip
          }
        }
      } catch (err) {
        console.error(`Failed to load DNS provider from ${file}:`, err.message);
      }
    }
  }
}

// Singleton
const registry = new DNSProviderRegistry();
registry.autoDiscover();

module.exports = registry;
