/**
 * OpenAI Whisper transcription provider.
 *
 * Uses POST /v1/audio/transcriptions (multipart/form-data).
 * Requires OPENAI_API_KEY env var.
 */

import type { TranscriptionProvider, TranscriptionInput, TranscriptionResult } from '../types.js';

export interface OpenAISTTConfig {
  apiKey: string;
  baseUrl?: string;
  model?: string;
}

export class OpenAITranscriptionProvider implements TranscriptionProvider {
  private config: Required<OpenAISTTConfig>;

  constructor(config?: Partial<OpenAISTTConfig>) {
    this.config = {
      apiKey: config?.apiKey ?? process.env.OPENAI_API_KEY ?? '',
      baseUrl: (
        config?.baseUrl ??
        process.env.OPENAI_BASE_URL ??
        'https://api.openai.com/v1'
      ).replace(/\/+$/, ''),
      model: config?.model ?? process.env.WHISPER_MODEL ?? 'whisper-1',
    };
  }

  isConfigured(): boolean {
    return Boolean(this.config.apiKey);
  }

  async transcribe(input: TranscriptionInput): Promise<TranscriptionResult> {
    if (!this.isConfigured()) {
      throw new Error('OpenAI is not configured (missing OPENAI_API_KEY)');
    }

    const effectiveModel = input.model || this.config.model;

    const formData = new FormData();
    formData.append('file', new Blob([input.audio]), input.filename);
    formData.append('model', effectiveModel);
    if (input.language) formData.append('language', input.language);
    if (input.prompt) formData.append('prompt', input.prompt);
    formData.append('response_format', 'verbose_json');

    const response = await fetch(`${this.config.baseUrl}/audio/transcriptions`, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${this.config.apiKey}`,
      },
      body: formData,
      signal: AbortSignal.timeout(120_000),
    });

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

    const data = (await response.json()) as {
      text: string;
      language?: string;
      duration?: number;
    };

    return {
      text: data.text,
      language: data.language ?? input.language ?? null,
      durationSeconds: data.duration ?? null,
      model: effectiveModel,
    };
  }
}
