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

/**
 * Send an OpenAI-compatible chat completion request to a provider.
 * Returns the parsed response or throws on HTTP/network errors.
 */
export async function sendChatCompletion(
  provider: ProviderConfig,
  modelId: string,
  request: ChatCompletionRequest,
  timeoutMs: number = 30_000
): Promise<{ response: ChatCompletionResponse; latencyMs: number; status: number }> {
  const apiKey = provider.apiKeyEnv ? process.env[provider.apiKeyEnv] : null;
  if (provider.apiKeyEnv && !apiKey) {
    throw new Error(`Missing API key: env var ${provider.apiKeyEnv} is not set`);
  }

  const url = `${provider.baseUrl}/chat/completions`;
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
    ...provider.extraHeaders,
  };
  if (apiKey) {
    headers.Authorization = `Bearer ${apiKey}`;
  }

  const body = JSON.stringify({
    model: modelId,
    messages: request.messages,
    ...(request.temperature !== undefined && { temperature: request.temperature }),
    ...(request.max_tokens !== undefined && { max_tokens: request.max_tokens }),
    ...(request.top_p !== undefined && { top_p: request.top_p }),
    stream: false,
  });

  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), timeoutMs);
  const start = Date.now();

  try {
    const res = await fetch(url, {
      method: 'POST',
      headers,
      body,
      signal: controller.signal,
    });

    const latencyMs = Date.now() - start;

    if (res.status === 429) {
      return {
        response: null as unknown as ChatCompletionResponse,
        latencyMs,
        status: 429,
      };
    }

    if (!res.ok) {
      const text = await res.text().catch(() => '');
      throw new Error(`${provider.name} returned ${res.status}: ${text.slice(0, 200)}`);
    }

    const data = (await res.json()) as ChatCompletionResponse;
    return { response: data, latencyMs, status: res.status };
  } finally {
    clearTimeout(timer);
  }
}
