import type { EmbeddingProvider } from '../types.js';

/**
 * OpenAI embedding provider
 *
 * Uses OpenAI's text-embedding-3-small or text-embedding-3-large models
 */
export class OpenAIEmbeddingProvider implements EmbeddingProvider {
  name = 'openai';
  model: string;
  dimensions: number;
  private apiKey: string;
  private baseUrl: string;

  constructor(options: {
    model?: 'text-embedding-3-small' | 'text-embedding-3-large';
    dimensions?: number;
    apiKey?: string;
    baseUrl?: string;
  } = {}) {
    this.model = options.model ?? 'text-embedding-3-small';
    this.dimensions = options.dimensions ?? (this.model === 'text-embedding-3-large' ? 3072 : 1536);
    this.apiKey = options.apiKey ?? process.env.OPENAI_API_KEY ?? '';
    this.baseUrl = options.baseUrl ?? 'https://api.openai.com/v1';

    if (!this.apiKey) {
      throw new Error('OpenAI API key is required. Set OPENAI_API_KEY environment variable.');
    }
  }

  async embed(texts: string[]): Promise<number[][]> {
    const response = await fetch(`${this.baseUrl}/embeddings`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${this.apiKey}`,
      },
      body: JSON.stringify({
        model: this.model,
        input: texts,
        dimensions: this.dimensions,
      }),
    });

    if (!response.ok) {
      const error = await response.text();
      throw new Error(`OpenAI embedding failed: ${error}`);
    }

    const data = await response.json() as {
      data: Array<{ embedding: number[]; index: number }>;
    };

    // Sort by index to preserve order
    return data.data
      .sort((a, b) => a.index - b.index)
      .map((item) => item.embedding);
  }

  async embedSingle(text: string): Promise<number[]> {
    const results = await this.embed([text]);
    return results[0];
  }
}
