import { IAIProvider, AIProviderConfig } from './types';
import { ConfigurationError } from '@flowlab/core'; // Assuming core exports errors

type AIProviderConstructor = new (config: AIProviderConfig) => IAIProvider;

export class AIProviderRegistry {
  private providers: Map<string, IAIProvider> = new Map();
  private constructors: Map<string, AIProviderConstructor> = new Map();
  private globalConfigs: Map<string, AIProviderConfig> = new Map();

  // Load global configurations (e.g., from env vars or a config file at startup)
  public loadGlobalConfigs(configs: Record<string, AIProviderConfig>): void {
    for (const name in configs) {
      this.globalConfigs.set(name.toLowerCase(), configs[name]);
    }
  }

  // Register a provider's constructor
  public registerProvider(name: string, constructor: AIProviderConstructor): void {
    this.constructors.set(name.toLowerCase(), constructor);
  }

  // Get or create a provider instance
  public getProvider(name: string, nodeSpecificConfig?: AIProviderConfig): IAIProvider {
    const lowerName = name.toLowerCase();
    // Use cached instance if config matches (simple check, might need deeper comparison)
    if (this.providers.has(lowerName) && !nodeSpecificConfig) {
        // TODO: Improve caching if config needs to be considered per instance
        // For now, assume global config instance is sufficient if no override
        return this.providers.get(lowerName)!;
    }

    const constructor = this.constructors.get(lowerName);
    if (!constructor) {
      throw new ConfigurationError(`AI provider "${name}" is not registered.`);
    }

    const globalConfig = this.globalConfigs.get(lowerName) || {};
    // Merge global config with node-specific config (node takes precedence)
    const effectiveConfig = { ...globalConfig, ...nodeSpecificConfig };

    if (!effectiveConfig.apiKey && !process.env[`${lowerName.toUpperCase()}_API_KEY`]) {
        // Attempt to load from common env var pattern if not provided
        // Consider more robust secret management in production
        console.warn(`API key for provider "${name}" not found in config or env var (${lowerName.toUpperCase()}_API_KEY).`);
    } else if (!effectiveConfig.apiKey) {
        effectiveConfig.apiKey = process.env[`${lowerName.toUpperCase()}_API_KEY`];
    }


    const instance = new constructor(effectiveConfig);

    // Cache instance only if using global config for simplicity now
    if (!nodeSpecificConfig) {
        this.providers.set(lowerName, instance);
    }

    return instance;
  }
}

// Default export for easy access
export const aiProviderRegistry = new AIProviderRegistry();