/**
 * Fallback LLM provider.
 *
 * Tries each provider in order, falling back to the next on error or
 * when a provider is not configured. Useful for resilient AI pipelines
 * (e.g. perplexity → openai → gemini).
 *
 * Usage:
 *   const llm = new FallbackLLMProvider([
 *     new PerplexityProvider(),
 *     new OpenAIProvider(),
 *     new GeminiProvider(),
 *   ]);
 */

import type { ChatCompletionRequest, ChatCompletionResponse, LLMProvider } from '../types.js';

export class FallbackLLMProvider implements LLMProvider {
  constructor(private readonly providers: LLMProvider[]) {
    if (providers.length === 0) {
      throw new Error('FallbackLLMProvider requires at least one provider');
    }
  }

  isConfigured(): boolean {
    return this.providers.some(p => p.isConfigured());
  }

  async chatCompletion(req: ChatCompletionRequest): Promise<ChatCompletionResponse> {
    const errors: string[] = [];

    for (const provider of this.providers) {
      if (!provider.isConfigured()) {
        errors.push(`${provider.constructor.name}: not configured`);
        continue;
      }
      try {
        return await provider.chatCompletion(req);
      } catch (err) {
        const msg = err instanceof Error ? err.message : String(err);
        errors.push(`${provider.constructor.name}: ${msg}`);
      }
    }

    throw new Error(`All LLM providers failed:\n${errors.map(e => `  - ${e}`).join('\n')}`);
  }
}
