import { db } from '@server/db/drizzle';
import { sql } from 'drizzle-orm';
import { initDatabase } from '@server/db/init';

interface OpenRouterModel {
  id: string;
  name: string;
  context_length: number;
  architecture?: {
    input_modalities?: string[];
    output_modalities?: string[];
  };
  supported_parameters?: string[];
}

const OPENROUTER_MODELS_URL = 'https://openrouter.ai/api/v1/models';
const SYNC_BATCH_SIZE = 50;

function isTextChatModel(m: OpenRouterModel): boolean {
  const inputs = m.architecture?.input_modalities ?? [];
  const outputs = m.architecture?.output_modalities ?? [];
  return inputs.includes('text') && outputs.includes('text');
}

function supportsTools(m: OpenRouterModel): boolean {
  return (m.supported_parameters ?? []).includes('tools');
}

function cleanDisplayName(raw: string): string {
  return raw.length > 60 ? raw.slice(0, 57) + '...' : raw;
}

export interface SyncResult {
  fetched: number;
  upserted: number;
  skipped: number;
  error?: string;
}

export async function syncOpenRouterModels(): Promise<SyncResult> {
  await initDatabase();

  /* raw: SELECT id FROM llm_providers WHERE name = 'openrouter' AND is_active = true */
  const { rows: providerRows } = await db.execute(sql`SELECT id FROM llm_providers WHERE name = 'openrouter' AND is_active = true`);
  const providerRow = providerRows[0] as { id: string } | undefined;
  if (!providerRow) {
    return { fetched: 0, upserted: 0, skipped: 0, error: 'OpenRouter provider not found' };
  }
  const providerId = providerRow.id;

  let models: OpenRouterModel[];
  try {
    const res = await fetch(OPENROUTER_MODELS_URL, {
      headers: { 'Accept': 'application/json' },
      signal: AbortSignal.timeout(20000),
    });
    if (!res.ok) {
      return { fetched: 0, upserted: 0, skipped: 0, error: `OpenRouter API error: ${res.status}` };
    }
    const data = await res.json() as { data?: OpenRouterModel[] };
    models = data.data ?? [];
  } catch (err: unknown) {
    return { fetched: 0, upserted: 0, skipped: 0, error: `Failed to fetch: ${err instanceof Error ? err.message : String(err)}` };
  }

  const chatModels = models.filter(isTextChatModel);

  let upserted = 0;
  let skipped = 0;

  for (let i = 0; i < chatModels.length; i += SYNC_BATCH_SIZE) {
    const batch = chatModels.slice(i, i + SYNC_BATCH_SIZE);
    for (const m of batch) {
      try {
        /* raw: INSERT INTO llm_models (...) VALUES (...) ON CONFLICT (...) DO UPDATE SET ... */
        await db.execute(sql`
          INSERT INTO llm_models (provider_id, model_id, display_name, context_length, supports_functions, is_active, display_order)
          VALUES (${providerId}, ${m.id}, ${cleanDisplayName(m.name)}, ${m.context_length ?? 0}, ${supportsTools(m)}, true, 100)
          ON CONFLICT (provider_id, model_id) DO UPDATE SET
            display_name = EXCLUDED.display_name,
            context_length = EXCLUDED.context_length,
            supports_functions = EXCLUDED.supports_functions,
            is_active = true
        `);
        upserted++;
      } catch {
        skipped++;
      }
    }
  }

  return { fetched: models.length, upserted, skipped };
}

export async function getOpenRouterModelCount(): Promise<number> {
  await initDatabase();
  /* raw: SELECT COUNT(*) as count FROM llm_models m JOIN llm_providers p ON p.id = m.provider_id WHERE p.name = 'openrouter' */
  const { rows } = await db.execute(sql`
    SELECT COUNT(*) as count FROM llm_models m
    JOIN llm_providers p ON p.id = m.provider_id
    WHERE p.name = 'openrouter'
  `);
  return parseInt((rows[0] as { count: string })?.count ?? '0', 10);
}

export async function listOpenRouterModels() {
  await initDatabase();
  /* raw: SELECT m.id, m.model_id, m.display_name, m.context_length, m.supports_functions FROM llm_models m JOIN llm_providers p ... */
  const { rows } = await db.execute(sql`
    SELECT m.id, m.model_id, m.display_name, m.context_length, m.supports_functions
    FROM llm_models m
    JOIN llm_providers p ON p.id = m.provider_id
    WHERE p.name = 'openrouter' AND m.is_active = true
    ORDER BY m.display_order, m.display_name
  `);
  return rows;
}
