import { assertAIConfigured, getActiveAIConfig } from "../config";
import type { AIProvider, TextGenerationRequest, TextGenerationResult } from "../types";

async function fetchWithTimeout(
  url: string,
  init: RequestInit,
  timeoutMs: number,
): Promise<Response> {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), timeoutMs);
  try {
    return await fetch(url, { ...init, signal: controller.signal });
  } finally {
    clearTimeout(timer);
  }
}

export const openaiProvider: AIProvider = {
  name: "openai",
  get model() {
    return getActiveAIConfig().model;
  },

  async generateText(request: TextGenerationRequest): Promise<TextGenerationResult> {
    const config = getActiveAIConfig();
    assertAIConfigured(config);

    const res = await fetchWithTimeout(
      "https://api.openai.com/v1/chat/completions",
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${config.apiKey}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          model: config.model,
          messages: [
            { role: "system", content: request.systemPrompt },
            { role: "user", content: request.userPrompt },
          ],
          temperature: 0.7,
        }),
      },
      config.timeoutMs,
    );

    const data = (await res.json()) as {
      choices?: Array<{ message?: { content?: string } }>;
      usage?: { prompt_tokens?: number; completion_tokens?: number; total_tokens?: number };
      error?: { message?: string };
    };

    if (!res.ok) {
      throw new Error(data.error?.message ?? "OpenAI text generation failed");
    }

    const content = data.choices?.[0]?.message?.content?.trim();
    if (!content) throw new Error("OpenAI returned empty content");

    return {
      content,
      provider: "openai",
      model: config.model,
      inputTokens: data.usage?.prompt_tokens,
      outputTokens: data.usage?.completion_tokens,
      totalTokens: data.usage?.total_tokens,
    };
  },
};
