/**
 * OpenRouter — OpenAI-compatible API for budget chat models.
 * Credentials: platform_settings first, then OPENROUTER_API_KEY env.
 */
import { getPlatformSettings } from './platformSettingsService.js';
import { chatCompletionTextWithCredentials, isLikelyChatModel } from './openaiService.js';

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

const OPENROUTER_REFERER =
  process.env.OPENROUTER_HTTP_REFERER?.trim() || process.env.PUBLIC_APP_URL?.trim() || 'https://support.appnotify.co.za';
const OPENROUTER_TITLE = process.env.OPENROUTER_X_TITLE?.trim() || 'Silicon Support';

/** Headers OpenRouter recommends for attribution and ranking. */
export function openRouterRequestHeaders(): Record<string, string> {
  return {
    'HTTP-Referer': OPENROUTER_REFERER,
    'X-Title': OPENROUTER_TITLE,
  };
}

/** Curated low-cost models for conversational / inter-agent use (OpenRouter model ids). */
export const OPENROUTER_BUDGET_MODELS = [
  'google/gemini-2.0-flash-lite-001',
  'google/gemini-flash-1.5-8b',
  'openai/gpt-4o-mini',
  'meta-llama/llama-3.2-3b-instruct:free',
  'qwen/qwen-2.5-7b-instruct',
  'mistralai/mistral-7b-instruct',
  'deepseek/deepseek-chat',
  'anthropic/claude-3-haiku',
] as const;

let credsCache: { key: string; model: string; at: number } | null = null;
const CACHE_TTL_MS = 60_000;

export function invalidateOpenRouterCredentialsCache(): void {
  credsCache = null;
}

export async function resolveOpenRouterCredentials(): Promise<{ key: string; model: string } | null> {
  const now = Date.now();
  if (credsCache && now - credsCache.at < CACHE_TTL_MS) {
    return credsCache.key ? { key: credsCache.key, model: credsCache.model } : null;
  }

  const row = await getPlatformSettings();
  const dbKey = row?.openrouter_api_key?.trim() ?? '';
  const envKey = process.env.OPENROUTER_API_KEY?.trim() ?? '';
  const key = dbKey || envKey;
  const model =
    row?.openrouter_model_id?.trim() ||
    process.env.OPENROUTER_MODEL_ID?.trim() ||
    OPENROUTER_BUDGET_MODELS[0];
  credsCache = { key, model, at: now };
  return key ? { key, model } : null;
}

export async function isOpenRouterConfigured(): Promise<boolean> {
  const c = await resolveOpenRouterCredentials();
  return Boolean(c?.key);
}

/** Chat-capable OpenRouter model ids (mirrors isLikelyChatModel exclusions). */
export function isLikelyOpenRouterChatModel(id: string): boolean {
  if (isLikelyChatModel(id)) return true;
  const lower = id.toLowerCase();
  if (
    lower.includes('embedding') ||
    lower.includes('moderation') ||
    lower.includes('whisper') ||
    lower.includes('tts') ||
    lower.includes('dall-e') ||
    lower.includes('realtime') ||
    lower.includes('audio') ||
    lower.includes('transcribe') ||
    lower.includes('search') ||
    lower.includes('rerank')
  ) {
    return false;
  }
  return id.includes('/');
}

/** Budget models plus any chat models returned by the live API (when key is set). */
export async function listOpenRouterModels(apiKey?: string): Promise<string[]> {
  const curated = [...OPENROUTER_BUDGET_MODELS];
  const key = apiKey?.trim();
  if (!key) return curated;

  try {
    const res = await fetch(`${OPENROUTER_DEFAULT_BASE}/models`, {
      headers: {
        Authorization: `Bearer ${key}`,
        ...openRouterRequestHeaders(),
      },
    });
    const raw = await res.text();
    if (!res.ok) return curated;
    const data = JSON.parse(raw) as { data?: Array<{ id: string }> };
    const live = (data.data ?? []).map(m => m.id).filter(isLikelyOpenRouterChatModel);
    const merged = [...new Set([...curated, ...live])];
    return merged.sort();
  } catch {
    return curated;
  }
}

export async function openRouterCompletionText(opts: {
  system: string;
  messages: Array<{ role: 'user' | 'assistant'; content: string }>;
  maxTokens?: number;
  model?: string;
  responseFormat?: 'json_object';
}): Promise<string> {
  const c = await resolveOpenRouterCredentials();
  if (!c?.key) throw new Error('No OpenRouter API key configured (Settings or OPENROUTER_API_KEY)');
  return chatCompletionTextWithCredentials({
    base: OPENROUTER_DEFAULT_BASE,
    apiKey: c.key,
    model: opts.model ?? c.model,
    system: opts.system,
    messages: opts.messages,
    maxTokens: opts.maxTokens,
    responseFormat: opts.responseFormat,
    extraHeaders: openRouterRequestHeaders(),
    providerLabel: 'OpenRouter',
  });
}
