/**
 * OpenRouter chat-completions caller.
 *
 * Talks to https://openrouter.ai/api/v1/chat/completions in OpenAI-compatible
 * format. Used as the OpenRouter side of `callLLMStage` so the existing
 * Anthropic call path stays untouched.
 *
 * JSON adherence: requests `response_format: { type: 'json_object' }`. DeepSeek
 * supports this (the API tolerates it as a hint when not natively supported,
 * per OpenAI-compat). The retry-on-parse-fail logic in call.ts is the safety
 * net for stragglers.
 */

import type { TokenUsage } from './pricing';
import type { ModelId } from './models';

const OPENROUTER_BASE = 'https://openrouter.ai/api/v1';

export interface OpenRouterChatResponse {
  text: string;
  usage: TokenUsage;
}

interface RawChatResponse {
  id: string;
  model: string;
  choices: Array<{
    index: number;
    message: { role: 'assistant'; content: string | null };
    finish_reason: string;
  }>;
  usage?: {
    prompt_tokens: number;
    completion_tokens: number;
    total_tokens?: number;
  };
  error?: { message: string; code?: number };
}

/**
 * Send a chat-completions request to OpenRouter and return the assistant's
 * text content + token usage. Throws on HTTP error or empty response.
 */
export async function callOpenRouterChat(opts: {
  model: ModelId;
  system: string;
  history: Array<{ role: 'user' | 'assistant'; content: string }>;
  maxTokens: number;
}): Promise<OpenRouterChatResponse> {
  const apiKey = process.env.OPENROUTER_API_KEY;
  if (!apiKey) {
    throw new Error(
      'OPENROUTER_API_KEY is not set. The OpenRouter pipeline cannot run without it.'
    );
  }

  const messages = [
    { role: 'system' as const, content: opts.system },
    ...opts.history,
  ];

  const body = {
    model: opts.model,
    messages,
    max_tokens: opts.maxTokens,
    response_format: { type: 'json_object' as const },
    // Provider preferences:
    //   - data_collection: 'deny'  → refuse any inference provider whose
    //     policy allows storing prompts/completions or training on them.
    //   - sort: 'throughput'       → among compliant providers, prefer the
    //     fastest one. V4 Pro deep-analysis was ~3.5min without this hint;
    //     with throughput sort it should land closer to ~1.5-2min.
    //   - allow_fallbacks: true    → still route across compliant providers
    //     when the primary is down (default, made explicit).
    // OpenRouter publishes per-provider data policies; data_collection is
    // the documented way to enforce a privacy floor at the API call level.
    // The account-level "opt out of training" toggle is the belt; this is
    // the braces.
    provider: {
      data_collection: 'deny' as const,
      sort: 'throughput' as const,
      allow_fallbacks: true,
    },
  };

  const res = await fetch(`${OPENROUTER_BASE}/chat/completions`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${apiKey}`,
      // OpenRouter uses these for analytics + their leaderboard.
      'HTTP-Referer':
        process.env.BETTER_AUTH_URL || 'https://pulse.wulfconsulting.cloud',
      'X-Title': 'Pulse Ticket Analyzer',
    },
    body: JSON.stringify(body),
  });

  if (!res.ok) {
    const text = await res.text().catch(() => '');
    throw new Error(
      `OpenRouter HTTP ${res.status}: ${text.slice(0, 500)}`
    );
  }

  const json = (await res.json()) as RawChatResponse;
  if (json.error) {
    throw new Error(`OpenRouter error: ${json.error.message}`);
  }
  const choice = json.choices?.[0];
  if (!choice) {
    throw new Error('OpenRouter returned no choices');
  }
  const text = (choice.message.content ?? '').trim();

  const usage: TokenUsage = {
    input_tokens: json.usage?.prompt_tokens ?? 0,
    output_tokens: json.usage?.completion_tokens ?? 0,
  };

  return { text, usage };
}

export function isOpenRouterConfigured(): boolean {
  return !!process.env.OPENROUTER_API_KEY;
}
