/* ============================================================
   RIVA — Réponses locales aux questions fréquentes
   Le bot lit la carte locale : aucune donnée client ne sort du restaurant.
   ============================================================ */

function faqTousLesPlats() {
  try { return Object.values(getEffectiveMenu().menu).flatMap(c => c.items); } catch (e) { return []; }
}
function faqCategorie(id) {
  try { return getEffectiveMenu().menu[id]?.items || []; } catch (e) { return []; }
}
function faqLister(items, max = 4) {
  return items.slice(0, max).map(i => `${i.name} (${i.price.toFixed(2)}€)`).join(', ');
}
function faqFourchette(items) {
  if (!items.length) return '';
  const prix = items.map(i => i.price);
  return `${Math.min(...prix).toFixed(2)}€ à ${Math.max(...prix).toFixed(2)}€`;
}

const MOTS_ALLERGENES = [
  'gluten', 'lactose', 'arachide', 'cacahuète', 'cacahuete', 'fruits à coque',
  'sésame', 'sesame', 'crustacé', 'crustace', 'mollusque', 'moutarde', 'soja',
];
function faqEstQuestionAllergie(question) {
  const q = normalize(question);
  const contexteAllergie = ['allergie', 'allergique', 'allergène', 'allergene', 'intolérant', 'intolerant', 'traces', 'sans allergène', 'sans allergene'];
  return contexteAllergie.some(m => q.includes(normalize(m))) || MOTS_ALLERGENES.some(m => q.includes(normalize(m)));
}
function faqTrouverPlat(question) {
  const q = normalize(question);
  if (q.trim().length < 3) return null;
  const plats = faqTousLesPlats();
  const correspondances = plats
    .filter(p => normalize(p.name).length >= 4 && q.includes(normalize(p.name)))
    .sort((a, b) => normalize(b.name).length - normalize(a.name).length);
  const GENERIQUES = new Set(['pizza', 'pizzas', 'panuozzo', 'panuozzos', 'pates', 'pasta', 'la', 'le', 'les', 'sur', 'mesure', 'maison', 'riva', 'plat', 'plats']);
  if (!correspondances.length) {
    const approx = plats.map(p => {
      const tokens = normalize(p.name).split(/\s+/).filter(w => w.length >= 5 && !GENERIQUES.has(w) && q.includes(w));
      return { plat: p, score: tokens.reduce((n, w) => n + w.length, 0) };
    }).filter(x => x.score > 0).sort((a, b) => b.score - a.score);
    if (approx.length) correspondances.push(approx[0].plat);
  }
  if (!correspondances.length) return null;
  if (/pates|linguine|penne|pasta/.test(q)) {
    const platPates = correspondances.find(p => String(p.catId).startsWith('pates'));
    if (platPates) return platPates;
  }
  if (/pizza/.test(q)) {
    const pizza = correspondances.find(p => /pizza/.test(p.catId));
    if (pizza) return pizza;
  }
  if (/panuozzo/.test(q)) {
    const panuozzo = correspondances.find(p => /panuozzo/.test(p.catId));
    if (panuozzo) return panuozzo;
  }
  return correspondances[0];
}
function faqResumeOptions(plat) {
  return (plat?.options || []).map(g => {
    const titre = g.titre.replace(/\s*[—–-].*$/, '').trim();
    const prix = g.prix ? ` (${g.prix.toFixed(2)}€ par choix)` : ' (compris)';
    return `• ${titre}${prix} : ${g.choix.join(', ')}`;
  }).join('\n');
}

/* Repérage prudent des allergènes possibles à partir des mots imprimés.
   Les recettes détaillées, fournisseurs et contaminations croisées doivent
   toujours être confirmés par l'équipe. */
function faqAllergenesPossibles(plat) {
  if (!plat) return [];
  const saisis = Array.isArray(plat.allergenes) ? plat.allergenes.map(x => String(x).trim()).filter(Boolean) : [];
  if (saisis.length) return saisis;
  const t = normalize(`${plat.name} ${plat.desc} ${plat.catLabel || ''} ${plat.catId || ''}`);
  const a = [];
  if (/pizza|panuozzo|souffle|pate|pates|linguine|penne|pain|crouton|brick|fricasse|samoussa|tarte|patisserie/.test(t)) a.push('gluten (pâte, pain ou préparation céréalière)');
  if (/fior di latte|boursin|fromage|parmigiano|parmesan|creme|maroilles|chevre|gorgonzola|stracciatella|burrata|mascarpone|mozzarella|lait/.test(t)) a.push('lait');
  if (/oeuf|œuf|jaune d/.test(t)) a.push('œufs');
  if (/thon|anchois|saumon/.test(t)) a.push('poisson');
  if (/scampi|crevette/.test(t)) a.push('crustacés');
  if (/fruits de mer/.test(t)) a.push('crustacés ou mollusques (détail à vérifier)');
  if (/pistache|noisette/.test(t)) a.push('fruits à coque (pistache ou noisette)');
  return [...new Set(a)];
}
function faqReponseAllergie(question, plat) {
  const possibles = faqAllergenesPossibles(plat);
  const q = normalize(question);
  const cite = plat ? `Pour ${plat.name}, ` : '';
  const sourceAllergenes = plat && Array.isArray(plat.allergenes) && plat.allergenes.some(x => String(x).trim());
  const liste = possibles.length
    ? sourceAllergenes
      ? `les allergènes renseignés sur sa fiche sont : ${possibles.join(', ')}.`
      : `les allergènes possibles d'après les ingrédients affichés sont : ${possibles.join(', ')}.`
    : plat
      ? `la description ne permet pas d'identifier avec certitude ses allergènes.`
      : `la carte mentionne notamment du gluten dans les pâtes, pizzas, panuozzos, soufflés, pains et certaines entrées ; du lait dans les recettes avec fromage ou crème ; des œufs, du poisson, des crustacés et des fruits à coque dans les plats où ces ingrédients sont indiqués.`;
  const ciblage = /sesame|arachide|cacahuete|soja|moutarde|celeri/.test(q)
    ? ` Cet allergène n'est pas indiqué dans la description consultée.`
    : '';
  return `${cite}${liste}${ciblage} Ce repérage ne confirme ni la recette complète ni l'absence de traces ou de contamination croisée. En cas d'allergie, demandez confirmation au personnel avant de commander.`;
}

// Réponses aux questions fréquentes, adaptées à la carte RIVA.
const LOCAL_FAQ = [
  {
    keywords: ['halal', 'halaal', 'haram', 'porc', 'sans porc'],
    answer: () => 'La carte indique des viandes halal. Pour une question sur un produit ou un ingrédient précis, demandez confirmation à l’équipe.',
  },
  {
    keywords: ['panuozzo', 'composer', 'composition'],
    answer: () => {
      const p = faqCategorie('panuozzo-sur-mesure')[0];
      return p
        ? `Le ${p.name} est à ${p.price.toFixed(2)}€ : le pain artisanal et une sauce maison sont compris. Choisissez les garnitures ci-dessous ; les ingrédients ajoutés sont facturés au prix indiqué.\n${faqResumeOptions(p)}`
        : 'Les panuozzos sont préparés à la demande. Consultez la catégorie Panuozzo sur mesure pour composer le vôtre.';
    },
  },
  {
    keywords: ['pizza sur mesure', 'composer ma pizza', 'composer une pizza', 'pizza a composer'],
    answer: () => {
      const p = faqCategorie('pizza-sur-mesure')[0];
      return p
        ? `La ${p.name} démarre à ${p.price.toFixed(2)}€ : le Fior di latte et une sauce sont compris. Choisissez les garnitures ci-dessous. Les tarifs des suppléments sont provisoires et restent à confirmer.\n${faqResumeOptions(p)}`
        : 'Les pizzas classiques et signatures sont à la carte. La composition personnalisée sera précisée par l’équipe.';
    },
  },
  {
    keywords: ['végétarien', 'vegetarien', 'végétarienne', 'veggie', 'sans viande', 'vegan', 'végan'],
    answer: () => {
      const plats = faqTousLesPlats().filter(i => /végétarien|vegetarien/i.test(i.name + ' ' + i.desc));
      return plats.length
        ? `La carte signale comme végétarien : ${faqLister(plats, 5)}. Pour une version sans produit laitier ou vegan, demandez confirmation à l’équipe.`
        : 'La carte ne comporte pas d’option vegan clairement identifiée. Demandez à l’équipe si une adaptation est possible.';
    },
  },
  {
    keywords: ['piquant', 'épicé', 'epice', 'spicy', 'pimenté', 'fort'],
    answer: () => {
      const plats = faqTousLesPlats().filter(i => /harissa|piment|épicé|relevé|spianata piccante/i.test(i.name + ' ' + i.desc));
      return plats.length
        ? `Les plats dont la description mentionne du piquant sont : ${faqLister(plats, 6)}. Demandez à l’équipe si le niveau peut être adapté.`
        : 'Demandez à l’équipe quels plats peuvent être préparés moins épicés.';
    },
  },
  {
    keywords: ['table', 'qr', 'scanner', 'sur place', 'salle'],
    answer: () => 'Sur place, scannez le QR code de votre table pour commander. Si vous commandez au comptoir ou avec la réceptionniste, indiquez votre numéro de table.',
  },
  {
    keywords: ['livraison', 'livrer', 'à domicile', 'domicile'],
    answer: () => SHOP.delivery.active === false
      ? 'La livraison n’est pas proposée pour le moment. Vous pouvez commander à emporter ou manger sur place.'
      : `Livraison en ${SHOP.delivery.time}, ${SHOP.delivery.radius}. Minimum ${SHOP.delivery.minOrder}€, frais ${SHOP.delivery.fee.toFixed(2)}€, offerts dès ${SHOP.delivery.freeAbove}€.`,
  },
  {
    keywords: ['emporter', 'collect', 'récupérer', 'retrait'],
    answer: () => `À emporter : ${SHOP.pickup.time} de préparation. Vous choisissez l’heure de retrait au moment de commander.`,
  },
  {
    keywords: ['horaire', 'ouvert', 'ouverture', 'fermeture', 'quand', 'jour'],
    answer: () => {
      const lignes = SHOP.hours.map(h => `${h.day} : ${h.slots}`).join('\n');
      return `${isOpenNow().label}.\n\n${lignes}`;
    },
  },
  {
    keywords: ['adresse', 'où', 'situe', 'localisation', 'denain', 'venir', 'parking'],
    answer: () => `RIVA se trouve au ${SHOP.address}. Le bouton Itinéraire en bas de page ouvre le trajet.`,
  },
  {
    keywords: ['téléphone', 'telephone', 'numéro', 'numero', 'appeler', 'tél', 'tel'],
    answer: () => SHOP.phone ? `Vous pouvez appeler RIVA au ${SHOP.phone}.` : 'Le numéro du restaurant n’est pas encore renseigné sur le site.',
  },
  {
    keywords: ['prix', 'tarif', 'combien', 'cher', 'budget'],
    answer: () => {
      const plats = faqTousLesPlats().filter(i => i.price < 60);
      return plats.length ? `Les plats vont de ${faqFourchette(plats)}. Le prix exact est affiché sur chaque plat ; les garnitures choisies peuvent ajouter un supplément.` : 'Les prix sont affichés sur la carte.';
    },
  },
  {
    keywords: ['paiement', 'payer', 'carte bancaire', 'cb', 'espèce', 'espece', 'ticket resto'],
    answer: () => 'Le paiement en ligne n’est pas disponible pour le moment. Pour les moyens de paiement acceptés au restaurant, demandez à l’équipe.',
  },
  {
    keywords: ['boisson', 'soda', 'alcool', 'bière', 'biere', 'vin', 'eau'],
    answer: () => {
      const b = faqCategorie('fraicheurs');
      return b.length ? `Boissons à la carte : ${faqLister(b, 6)}. Consultez la carte pour les parfums et formats disponibles.` : 'Consultez la catégorie Les Fraîcheurs pour les boissons disponibles.';
    },
  },
  {
    keywords: ['merci', 'thanks', 'super', 'cool', 'top', 'parfait'],
    answer: () => 'Avec plaisir !',
  },
  {
    keywords: ['salut', 'bonjour', 'hello', 'coucou', 'bonsoir'],
    answer: () => 'Bonjour ! Je réponds aux questions sur la carte RIVA, les compositions, les allergènes, les horaires et les commandes. Qu’est-ce qui vous ferait plaisir ?',
  },
];

const RATE_LIMIT_MAX = 30;
const RATE_LIMIT_WINDOW_MS = 60 * 60 * 1000;
function checkRateLimit() {
  try {
    const now = Date.now();
    const history = JSON.parse(localStorage.getItem('bt-ia-historique') || '[]');
    const recent = history.filter(t => now - t < RATE_LIMIT_WINDOW_MS);
    if (recent.length >= RATE_LIMIT_MAX) {
      const waitMin = Math.ceil((RATE_LIMIT_WINDOW_MS - (now - recent[0])) / 60000);
      return { ok: false, waitMin };
    }
    return { ok: true, remaining: RATE_LIMIT_MAX - recent.length };
  } catch (e) { return { ok: true, remaining: RATE_LIMIT_MAX }; }
}
function trackQuestion() {
  try {
    const now = Date.now();
    const history = JSON.parse(localStorage.getItem('bt-ia-historique') || '[]');
    const recent = history.filter(t => now - t < RATE_LIMIT_WINDOW_MS);
    recent.push(now);
    localStorage.setItem('bt-ia-historique', JSON.stringify(recent.slice(-50)));
  } catch (e) {}
}

function normalize(s) {
  return String(s || '').toLowerCase()
    .normalize('NFD').replace(/[̀-ͯ]/g, '')
    .replace(/[^a-z0-9\s]/g, ' ');
}
function chercherPlat(question) {
  const plat = faqTrouverPlat(question);
  if (!plat) return null;
  if (faqEstQuestionAllergie(question)) return faqReponseAllergie(question, plat);
  const parts = [`${plat.name} — ${plat.price.toFixed(2)}€${plat.desc ? ' : ' + plat.desc : ''}`];
  if (plat.options && plat.options.length) {
    parts.push('Choix à faire : ' + plat.options.map(g => g.titre.split('—')[0].trim()).join(', ') + '.');
  }
  if (plat.catId === 'pizza-sur-mesure' || plat.catId === 'panuozzo-sur-mesure') {
    parts.push(faqResumeOptions(plat));
  }
  if (plat.catId === 'pizza-sur-mesure') parts.push('Les tarifs des suppléments sont provisoires et restent à confirmer.');
  parts.push(`Catégorie : ${plat.catLabel}.`);
  return parts.join('\n');
}
function tryLocalFaq(question) {
  const plat = faqTrouverPlat(question);
  if (faqEstQuestionAllergie(question)) return faqReponseAllergie(question, plat);
  const parPlat = chercherPlat(question);
  if (parPlat) return parPlat;
  const normalized = normalize(question);
  for (const entry of LOCAL_FAQ) {
    for (const kw of entry.keywords) {
      if (normalized.includes(normalize(kw))) return entry.answer();
    }
  }
  return null;
}

const CACHE_TTL_MS = 60 * 60 * 1000;
function getCachedAnswer(question) {
  try {
    const cache = JSON.parse(localStorage.getItem('bt-ia-cache') || '{}');
    const key = normalize(question).slice(0, 100);
    const entry = cache[key];
    if (entry && Date.now() - entry.t < CACHE_TTL_MS) return entry.a;
  } catch (e) {}
  return null;
}
function setCachedAnswer(question, answer) {
  try {
    const cache = JSON.parse(localStorage.getItem('bt-ia-cache') || '{}');
    const key = normalize(question).slice(0, 100);
    cache[key] = { a: answer, t: Date.now() };
    const keys = Object.keys(cache);
    if (keys.length > 50) {
      keys.sort((a, b) => cache[a].t - cache[b].t).slice(0, keys.length - 50).forEach(k => delete cache[k]);
    }
    localStorage.setItem('bt-ia-cache', JSON.stringify(cache));
  } catch (e) {}
}
Object.assign(window, { LOCAL_FAQ, tryLocalFaq, chercherPlat, checkRateLimit, trackQuestion, getCachedAnswer, setCachedAnswer });
