// src/llm/provider.js
// Pluggable AI provider for the chat widget — mirrors the LINK App's AI
// Advisor pattern: Groq as the free, fast default, with NVIDIA as a
// configurable fallback if you switch providers later.

const SYSTEM_PROMPT = `You are the assistant for Yellow Stone Traders & General Supplies, a Tanzanian contracting and general supplies company founded by Matemla Michael Lameck. The company works across three lines of business:

Gold mining:
- Gold prospecting, extraction and processing under the company's own Primary Mining Licence in the Kigosi goldfields, Bukombe District

Construction & contracting:
- Road contracting and construction of government projects (schools, dispensaries)
- Construction and contracting for private individuals and companies
- General building construction
- Construction of railways and other specialized/utility projects
- Architectural and engineering blueprints/drafting for various projects

Mining supply & consultancy:
- Sale of mining/excavation equipment
- Supply of ore-processing (beneficiation) chemicals, including for gold recovery
- Consultancy on best practices for ore processing and stone beneficiation

Answer questions about these services, how the process works (consultation, design/drafting, procurement, construction, handover), and how to request a quote. Keep replies short (2-4 sentences), professional, and practical. If someone wants a quote, a site visit, or to discuss a tender, direct them to the Contact page, phone +255 787 094 468, or email info@yst.co.tz. If you don't know something specific (exact pricing, project history, licensing details), say so honestly and suggest contacting the team directly. Do not invent statistics, prices, or completed projects you were not given.`;

async function callGroq(messages, systemPrompt = SYSTEM_PROMPT, opts = {}) {
  const apiKey = process.env.GROQ_API_KEY;
  if (!apiKey) throw new Error('GROQ_API_KEY not configured');
  const model = process.env.GROQ_MODEL || 'llama-3.1-8b-instant';

  const resp = await fetch('https://api.groq.com/openai/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${apiKey}`
    },
    body: JSON.stringify({
      model,
      messages: [{ role: 'system', content: systemPrompt }, ...messages],
      temperature: opts.temperature ?? 0.4,
      max_tokens: opts.maxTokens ?? 300
    })
  });

  if (!resp.ok) {
    const text = await resp.text().catch(() => '');
    throw new Error(`Groq API error ${resp.status}: ${text}`);
  }
  const data = await resp.json();
  return data.choices?.[0]?.message?.content?.trim() || "Sorry, I couldn't generate a reply just now.";
}

async function callNvidia(messages, systemPrompt = SYSTEM_PROMPT, opts = {}) {
  const apiKey = process.env.NVIDIA_API_KEY;
  if (!apiKey) throw new Error('NVIDIA_API_KEY not configured');
  const model = process.env.NVIDIA_MODEL || 'meta/llama-3.1-8b-instruct';

  const resp = await fetch('https://integrate.api.nvidia.com/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Authorization: `Bearer ${apiKey}`
    },
    body: JSON.stringify({
      model,
      messages: [{ role: 'system', content: systemPrompt }, ...messages],
      temperature: opts.temperature ?? 0.4,
      max_tokens: opts.maxTokens ?? 300
    })
  });

  if (!resp.ok) {
    const text = await resp.text().catch(() => '');
    throw new Error(`NVIDIA API error ${resp.status}: ${text}`);
  }
  const data = await resp.json();
  return data.choices?.[0]?.message?.content?.trim() || "Sorry, I couldn't generate a reply just now.";
}

// Simple keyword fallback so the widget still says something useful if no
// API key is configured at all (first-run / before you add a key).
function offlineFallback(messages) {
  const last = (messages[messages.length - 1]?.content || '').toLowerCase();
  if (/quote|price|cost|estimate/.test(last)) {
    return "For an accurate quote we'll need a few details about your project (location, scope, timeline). Please use the Contact form, call +255 787 094 468, or email info@yst.co.tz and our team will follow up.";
  }
  if (/road|highway/.test(last)) {
    return "We handle road contracting — construction, upgrading and rehabilitation — for both government and private clients. Share your project location and scope via the Contact page and we'll arrange a site assessment.";
  }
  if (/school|dispensary|clinic|government/.test(last)) {
    return "We construct government infrastructure including schools and dispensaries, built to national standards. Reach out via the Contact page with the tender or project details and our team will respond.";
  }
  if (/mining|excavat|equipment/.test(last)) {
    return "We supply mining and excavation equipment for small- and large-scale operations. Tell us what you need via the Contact page or email info@yst.co.tz and we'll advise on availability.";
  }
  if (/chemical|process|ore|gold|beneficiation/.test(last)) {
    return "We supply ore-processing chemicals and advise on best-practice ore processing and stone beneficiation. For a technical consultation, please reach out through the Contact page.";
  }
  if (/blueprint|drawing|plan|design|drafting/.test(last)) {
    return "Our team prepares architectural and engineering blueprints for a range of projects. Share your project brief via the Contact page and we'll scope the drafting work.";
  }
  return "Thanks for reaching out! I'm running in offline mode right now — for a full answer, please contact our team directly at info@yst.co.tz or +255 787 094 468.";
}

// Generic single-shot completion for admin-side AI helpers (currently:
// polishing an invoice's purpose-of-payment + cover message). Unlike the
// chat widget, there is no offline keyword fallback here — if no provider
// is configured or both fail, the caller should surface an error so the
// admin knows to write the text themselves rather than silently getting a
// canned reply printed on a real invoice.
async function completeText(systemPrompt, userPrompt, opts = {}) {
  const provider = (process.env.LLM_PROVIDER || 'groq').toLowerCase();
  const messages = [{ role: 'user', content: userPrompt }];
  try {
    if (provider === 'nvidia') return await callNvidia(messages, systemPrompt, opts);
    return await callGroq(messages, systemPrompt, opts);
  } catch (err) {
    console.error('[ai] primary provider failed:', err.message);
    if (provider === 'nvidia') return await callGroq(messages, systemPrompt, opts);
    return await callNvidia(messages, systemPrompt, opts);
  }
}

async function getChatReply(messages) {
  const provider = (process.env.LLM_PROVIDER || 'groq').toLowerCase();
  try {
    if (provider === 'nvidia') return await callNvidia(messages);
    return await callGroq(messages);
  } catch (err) {
    console.error('[chat] primary provider failed:', err.message);
    try {
      // try the other provider as a fallback if configured
      if (provider === 'nvidia') return await callGroq(messages);
      return await callNvidia(messages);
    } catch (err2) {
      console.error('[chat] fallback provider also failed:', err2.message);
      return offlineFallback(messages);
    }
  }
}

module.exports = { getChatReply, completeText };
