'use strict';

function normalizeProvider(value = process.env.AI_PROVIDER) {
  const provider = String(value || '').trim().toLowerCase();
  if (!provider) return 'openai';
  if (['openai', 'chatgpt', 'gpt'].includes(provider)) return 'openai';
  return 'anthropic';
}

function selectedProviderConfig(env = process.env) {
  let provider = normalizeProvider(env.AI_PROVIDER);
  // Una configuracion antigua puede conservar AI_PROVIDER=anthropic aunque el
  // usuario ya haya capturado exclusivamente una llave OpenAI. Elegimos el
  // proveedor utilizable para evitar exigir la llave del proveedor equivocado.
  if (provider === 'anthropic' && !String(env.ANTHROPIC_API_KEY || '').trim() && String(env.OPENAI_API_KEY || '').trim()) provider = 'openai';
  if (provider === 'openai' && !String(env.OPENAI_API_KEY || '').trim() && String(env.ANTHROPIC_API_KEY || '').trim()) provider = 'anthropic';
  if (provider === 'openai') {
    return {
      provider,
      apiKey: env.OPENAI_API_KEY || '',
      model: env.OPENAI_MODEL || 'gpt-5.6-terra',
    };
  }
  return {
    provider,
    apiKey: env.ANTHROPIC_API_KEY || '',
    model: env.ANTHROPIC_MODEL || 'claude-sonnet-4-6',
  };
}

function extractOpenAiText(data) {
  if (typeof data?.output_text === 'string') return data.output_text;
  const parts = [];
  for (const item of data?.output || []) {
    for (const content of item?.content || []) {
      if (typeof content?.text === 'string') parts.push(content.text);
      if (typeof content?.output_text === 'string') parts.push(content.output_text);
    }
  }
  return parts.join('\n').trim();
}

async function callAnthropic({ apiKey, model, system, input, maxTokens = 1024, fetchImpl = fetch }) {
  const response = await fetchImpl('https://api.anthropic.com/v1/messages', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': apiKey,
      'anthropic-version': '2023-06-01',
    },
    body: JSON.stringify({
      model,
      max_tokens: maxTokens,
      system,
      messages: [{ role: 'user', content: input }],
    }),
  });

  if (!response.ok) {
    const errText = await response.text();
    let errMsg = `Error Anthropic API (${response.status})`;
    try {
      const errJson = JSON.parse(errText);
      errMsg = errJson?.error?.message || errMsg;
    } catch (_) {}
    const error = new Error(errMsg);
    error.status = response.status;
    throw error;
  }

  const data = await response.json();
  return data?.content?.[0]?.text || '';
}

async function callOpenAi({ apiKey, model, system, input, maxTokens = 1024, reasoningEffort = 'high', fetchImpl = fetch }) {
  const response = await fetchImpl('https://api.openai.com/v1/responses', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${apiKey}`,
    },
    body: JSON.stringify({
      model,
      instructions: system,
      input,
      max_output_tokens: maxTokens,
      reasoning: { effort: reasoningEffort },
      store: false,
    }),
  });

  if (!response.ok) {
    const errText = await response.text();
    let errMsg = `Error OpenAI API (${response.status})`;
    try {
      const errJson = JSON.parse(errText);
      errMsg = errJson?.error?.message || errMsg;
    } catch (_) {}
    const error = new Error(errMsg);
    error.status = response.status;
    throw error;
  }

  const data = await response.json();
  return extractOpenAiText(data);
}

async function callSelectedAi({ system, input, maxTokens = 1024, reasoningEffort = 'high', env = process.env, fetchImpl = fetch }) {
  const config = selectedProviderConfig(env);
  if (!config.apiKey || !String(config.apiKey).trim()) {
    const envName = config.provider === 'openai' ? 'OPENAI_API_KEY' : 'ANTHROPIC_API_KEY';
    const error = new Error(`${envName} no configurada. Agregala en Arkhon Engineering.`);
    error.status = 503;
    error.provider = config.provider;
    throw error;
  }

  const text = config.provider === 'openai'
    ? await callOpenAi({ apiKey: config.apiKey, model: config.model, system, input, maxTokens, reasoningEffort, fetchImpl })
    : await callAnthropic({ apiKey: config.apiKey, model: config.model, system, input, maxTokens, fetchImpl });

  return { provider: config.provider, model: config.model, text };
}

module.exports = {
  normalizeProvider,
  selectedProviderConfig,
  extractOpenAiText,
  callSelectedAi,
};
