/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import { ProviderRegistry } from './registry.js';
import { OpenAIProvider } from './openai.js';
import { AnthropicProvider } from './anthropic.js';
import { GeminiProvider } from './gemini.js';
import { ZenProvider } from './zen.js';
/**
 * Manages AI providers with fallback and load balancing
 */
export class ProviderManager {
    registry;
    configs;
    constructor(configs) {
        this.registry = new ProviderRegistry();
        this.configs = configs;
        this.initializeProviders();
    }
    initializeProviders() {
        for (const config of this.configs) {
            if (!config.enabled || !config.apiKey) {
                console.log(`Skipping disabled provider: ${config.name}`);
                continue;
            }
            let provider;
            try {
                switch (config.name) {
                    case 'openai':
                        provider = new OpenAIProvider(config);
                        break;
                    case 'anthropic':
                        provider = new AnthropicProvider(config);
                        break;
                    case 'gemini':
                        provider = new GeminiProvider(config);
                        break;
                    case 'zen':
                        provider = new ZenProvider(config);
                        break;
                    default:
                        console.warn(`Unknown provider: ${config.name}`);
                        continue;
                }
                this.registry.register(provider);
                this.registry.registerConfig(config);
                console.log(`✅ Initialized provider: ${config.name} (priority: ${config.priority})`);
            }
            catch (error) {
                console.error(`❌ Failed to initialize provider ${config.name}:`, error);
            }
        }
    }
    /**
     * Execute with automatic fallback to available providers
     */
    async executeWithFallback(prompt, options = {}) {
        const providers = this.registry.getEnabledProviders();
        if (providers.length === 0) {
            throw new Error('No AI providers available. Please configure at least one provider.');
        }
        const errors = [];
        for (const provider of providers) {
            try {
                // Check if provider is within rate limits
                if (await this.isRateLimited(provider)) {
                    console.log(`⏭️ Skipping ${provider.name} due to rate limits`);
                    continue;
                }
                console.log(`🤖 Executing with ${provider.name}...`);
                const response = await provider.execute(prompt, options);
                // Update usage tracking
                await this.updateUsageTracking(provider.name, response.usage);
                return response;
            }
            catch (error) {
                const errorMsg = `${provider.name}: ${error instanceof Error ? error.message : 'Unknown error'}`;
                console.warn(`❌ ${errorMsg}`);
                errors.push(errorMsg);
                continue;
            }
        }
        throw new Error(`All providers failed:\n${errors.join('\n')}`);
    }
    /**
     * Execute with a specific provider
     */
    async executeWithProvider(providerName, prompt, options = {}) {
        const provider = this.registry.getProvider(providerName);
        if (!provider) {
            throw new Error(`Provider '${providerName}' not found or not enabled`);
        }
        if (!this.registry.isProviderAvailable(providerName)) {
            throw new Error(`Provider '${providerName}' is not available`);
        }
        try {
            const response = await provider.execute(prompt, options);
            await this.updateUsageTracking(providerName, response.usage);
            return response;
        }
        catch (error) {
            throw new Error(`Provider '${providerName}' failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
        }
    }
    /**
     * Get available providers
     */
    getAvailableProviders() {
        return this.registry.getAvailableProviders();
    }
    /**
     * Get a provider instance by name
     */
    getProvider(name) {
        return this.registry.getProvider(name);
    }
    /**
     * Get provider information
     */
    async getProviderInfo(providerName) {
        const provider = this.registry.getProvider(providerName);
        if (!provider)
            return null;
        try {
            const [models, limits] = await Promise.all([
                provider.getModels(),
                provider.checkLimits(),
            ]);
            return {
                available: this.registry.isProviderAvailable(providerName),
                models,
                limits,
            };
        }
        catch (error) {
            return {
                available: false,
                models: [],
                limits: null,
            };
        }
    }
    /**
     * Test all providers
     */
    async testProviders() {
        const results = {};
        const providers = this.registry.getAvailableProviders();
        for (const providerName of providers) {
            const provider = this.registry.getProvider(providerName);
            if (provider) {
                try {
                    results[providerName] = await provider.validateConnection();
                }
                catch {
                    results[providerName] = false;
                }
            }
            else {
                results[providerName] = false;
            }
        }
        return results;
    }
    async isRateLimited(provider) {
        try {
            const limits = await provider.checkLimits();
            const currentUsage = limits.currentUsage;
            if (!currentUsage)
                return false;
            // Simple rate limiting check
            const limitsReached = currentUsage.requestsToday >= limits.requestsPerDay ||
                currentUsage.tokensToday >= limits.tokensPerDay;
            return limitsReached;
        }
        catch {
            // If we can't check limits, assume it's OK
            return false;
        }
    }
    async updateUsageTracking(providerName, usage) {
        // In a real implementation, this would update a local database
        // or send to a usage tracking service
        console.log(`📊 ${providerName} usage: ${usage.totalTokens} tokens`);
    }
    /**
     * Get usage statistics
     */
    async getUsageStats() {
        return await this.registry.getUsageStats();
    }
}
//# sourceMappingURL=manager.js.map