// Provider-agnostic chat completion. Returns string, throws Error with friendly messages.
async function callAI({ provider, apiKey, system, user, json = false, signal }) {
  if (!apiKey) throw new Error("No API key set. Scroll up to Section 5 to add one.");
  if (provider === "openrouter") {
    return await callOpenRouter({ apiKey, system, user, json, signal });
  } else if (provider === "gemini") {
    return await callGemini({ apiKey, system, user, json, signal });
  } else {
    throw new Error("Unknown provider.");
  }
}

async function callOpenRouter({ apiKey, system, user, json, signal }) {
  let res;
  try {
    res = await fetch("https://openrouter.ai/api/v1/chat/completions", {
      method: "POST",
      signal,
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${apiKey}`,
        "HTTP-Referer": location.origin || "https://example.com",
        "X-Title": "Data job-hunt guide",
      },
      body: JSON.stringify({
        model: "google/gemini-2.0-flash-exp:free",
        messages: [
          ...(system ? [{ role: "system", content: system }] : []),
          { role: "user", content: user },
        ],
        ...(json ? { response_format: { type: "json_object" } } : {}),
        temperature: 0.7,
      }),
    });
  } catch (e) {
    if (e.name === "AbortError") throw e;
    throw new Error("Network error — can't reach OpenRouter. Check your connection.");
  }
  if (!res.ok) {
    const body = await res.text().catch(() => "");
    if (res.status === 401) throw new Error("Invalid OpenRouter key. Double-check it in Section 5.");
    if (res.status === 402) throw new Error("OpenRouter says this model needs credits. Try a :free model.");
    if (res.status === 429) throw new Error("Rate limited by OpenRouter. Wait a minute and retry.");
    throw new Error(`OpenRouter error ${res.status}: ${body.slice(0, 200) || "unknown"}`);
  }
  const data = await res.json();
  const text = data?.choices?.[0]?.message?.content;
  if (!text) throw new Error("Empty response from OpenRouter. Try again.");
  return text;
}

async function callGemini({ apiKey, system, user, json, signal }) {
  const model = "gemini-2.0-flash-exp";
  const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${encodeURIComponent(apiKey)}`;
  let res;
  try {
    res = await fetch(url, {
      method: "POST",
      signal,
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        ...(system ? { systemInstruction: { parts: [{ text: system }] } } : {}),
        contents: [{ role: "user", parts: [{ text: user }] }],
        generationConfig: {
          temperature: 0.7,
          ...(json ? { responseMimeType: "application/json" } : {}),
        },
      }),
    });
  } catch (e) {
    if (e.name === "AbortError") throw e;
    throw new Error("Network error — can't reach Google AI. Check your connection.");
  }
  if (!res.ok) {
    const body = await res.text().catch(() => "");
    if (res.status === 400 && /API key/i.test(body)) throw new Error("Invalid Gemini key. Double-check it in Section 5.");
    if (res.status === 401 || res.status === 403) throw new Error("Gemini rejected the key. Double-check it in Section 5.");
    if (res.status === 429) throw new Error("Rate limited by Gemini. Wait a minute and retry.");
    throw new Error(`Gemini error ${res.status}: ${body.slice(0, 200) || "unknown"}`);
  }
  const data = await res.json();
  const text = data?.candidates?.[0]?.content?.parts?.map(p => p.text).join("") || "";
  if (!text) {
    const reason = data?.promptFeedback?.blockReason;
    if (reason) throw new Error(`Gemini blocked the response (${reason}). Try rewording.`);
    throw new Error("Empty response from Gemini. Try again.");
  }
  return text;
}

// Helper to extract JSON from a model response that might include stray prose.
function parseJSONLoose(text) {
  try { return JSON.parse(text); } catch {}
  const m = text.match(/```json\s*([\s\S]*?)```/i) || text.match(/```\s*([\s\S]*?)```/);
  if (m) { try { return JSON.parse(m[1]); } catch {} }
  const first = text.indexOf("{"); const last = text.lastIndexOf("}");
  if (first !== -1 && last > first) {
    try { return JSON.parse(text.slice(first, last + 1)); } catch {}
  }
  throw new Error("The model didn't return clean JSON. Try again.");
}

window.callAI = callAI;
window.parseJSONLoose = parseJSONLoose;
