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 anthropicProvider: AIProvider = {
  name: "anthropic",
  get model() {
    return getActiveAIConfig().model;
  },

  async generateText(request: TextGenerationRequest): Promise<TextGenerationResult> {
    const config = getActiveAIConfig();
    assertAIConfigured(config);

    const res = await fetchWithTimeout(
      "https://api.anthropic.com/v1/messages",
      {
        method: "POST",
        headers: {
          "x-api-key": config.apiKey,
          "anthropic-version": "2023-06-01",
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          model: config.model,
          max_tokens: 1800,
          system: request.systemPrompt,
          messages: [{ role: "user", content: request.userPrompt }],
        }),
      },
      config.timeoutMs,
    );

    const data = (await res.json()) as {
      content?: Array<{ type: string; text?: string }>;
      usage?: { input_tokens?: number; output_tokens?: number };
      error?: { message?: string };
    };

    if (!res.ok) {
      throw new Error(data.error?.message ?? "Anthropic text generation failed");
    }

    const content = data.content
      ?.filter((block) => block.type === "text")
      .map((block) => block.text ?? "")
      .join("")
      .trim();

    if (!content) throw new Error("Anthropic returned empty content");

    const inputTokens = data.usage?.input_tokens;
    const outputTokens = data.usage?.output_tokens;

    return {
      content,
      provider: "anthropic",
      model: config.model,
      inputTokens,
      outputTokens,
      totalTokens:
        inputTokens != null && outputTokens != null ? inputTokens + outputTokens : undefined,
    };
  },
};
