// site/data-backend.jsx — Adapter d'invités live (Sheet → fuzzy match RSVP)
//
// Le site charge ici la liste d'invités depuis le Google Sheet (via
// backend/config.js). Si le backend est indisponible, on retombe sur
// DATA.invites (statique). La liste est mise en cache 10 min côté
// localStorage par le helper BACKEND.getInvitesCached().
//
// Format normalisé renvoyé : [{ id, name, prenom, nom, cote, categorie }]
//   - `id` peut être null si l'invité vient du fallback statique
//   - `name` = "Prénom Nom" propre, utilisé pour l'affichage + fuzzy match

// Convertit DATA.invites (array de "Prénom Nom") en objets {id:null, name, prenom, nom}.
// Permet au site de fonctionner même backend HS au premier chargement.
function staticInvitesFallback() {
  return (window.DATA?.invites || []).map((full, i) => {
    const parts = String(full).trim().split(/\s+/);
    const prenom = parts[0] || "";
    const nom = parts.slice(1).join(" ") || "";
    return {
      id: null, name: full, prenom, nom,
      cote: "", categorie: "",
      plus_one_max: 0, enfant_max: 0,
      rsvp_statut: "en_attente", rsvp_via: "", partner_id: "", plus_one_of: "",
    };
  });
}

// Normalise un objet invité backend → format unifié
function adaptBackendInvite(inv) {
  const prenom = inv.prenom || "";
  const nom = inv.nom || "";
  const name = `${prenom} ${nom}`.trim() || "(sans nom)";
  return {
    id: inv.id || null,
    name,
    prenom,
    nom,
    cote: inv.cote || "",
    categorie: inv.categorie || "",
    plus_one_max: Number(inv.plus_one_max) || 0,
    enfant_max: Number(inv.enfant_max) || 0,
    rsvp_statut: inv.rsvp_statut || "en_attente",
    rsvp_via: inv.rsvp_via || "",
    partner_id: inv.partner_id || "",
    plus_one_of: inv.plus_one_of || "",
  };
}

// Hook React : récupère la liste live des invités.
// Renvoie { invites, loading, source } où source = "backend" | "cache" | "fallback".
// Refait un fetch automatiquement quand l'événement "ea-backend:invalidate"
// est dispatché (ex: après un submitRsvp réussi).
function useGuestList() {
  const fallback = React.useMemo(() => staticInvitesFallback(), []);
  const [state, setState] = React.useState({
    invites: fallback,
    loading: true,
    source: "fallback",
  });
  const [reloadKey, setReloadKey] = React.useState(0);

  React.useEffect(() => {
    let alive = true;
    (async () => {
      if (!window.BACKEND) {
        if (alive) setState({ invites: fallback, loading: false, source: "fallback" });
        return;
      }
      try {
        const list = await window.BACKEND.getInvitesCached([]);
        if (!alive) return;
        if (Array.isArray(list) && list.length > 0) {
          const invites = list.map(adaptBackendInvite);
          setState({ invites, loading: false, source: "backend" });
        } else {
          setState({ invites: fallback, loading: false, source: "fallback" });
        }
      } catch (e) {
        console.warn("[site] useGuestList failed", e);
        if (alive) setState({ invites: fallback, loading: false, source: "fallback" });
      }
    })();
    return () => { alive = false; };
  }, [fallback, reloadKey]);

  // Écoute l'invalidation de cache pour refetcher
  React.useEffect(() => {
    const onInvalidate = () => setReloadKey(k => k + 1);
    window.addEventListener("ea-backend:invalidate", onInvalidate);
    return () => window.removeEventListener("ea-backend:invalidate", onInvalidate);
  }, []);

  return state;
}

// File d'attente RSVP non envoyés (retry au prochain chargement)
const RSVP_QUEUE_KEY = "ea-backend:rsvp-queue";

function enqueueRsvp(payload) {
  try {
    const q = JSON.parse(localStorage.getItem(RSVP_QUEUE_KEY) || "[]");
    q.push({ ...payload, queued_at: new Date().toISOString() });
    localStorage.setItem(RSVP_QUEUE_KEY, JSON.stringify(q));
  } catch {}
}

// Tente d'envoyer une RSVP au backend. Renvoie { ok, error?, queued? }.
// Si le backend est indisponible ou retourne KO, met en file d'attente.
// En cas de succès, invalide aussi le cache des invités pour que la liste
// (statut, badges "déjà inscrit") se rafraîchisse immédiatement.
async function submitRsvpToBackend(payload) {
  if (!window.BACKEND) {
    enqueueRsvp(payload);
    return { ok: false, queued: true, error: "Backend non chargé" };
  }
  try {
    const res = await window.BACKEND.post("submitRsvp", payload);
    if (res?.ok) {
      window.BACKEND.invalidateInvitesCache?.();
      return { ok: true, response: res };
    }
    enqueueRsvp(payload);
    return { ok: false, queued: true, error: res?.error || "Réponse invalide du serveur" };
  } catch (e) {
    enqueueRsvp(payload);
    return { ok: false, queued: true, error: e.message };
  }
}

// Récupère la RSVP complète d'un invité (autofill quand il revient sur le
// formulaire). Inclut les lignes enfants liées.
async function fetchMyRsvp(inviteId) {
  if (!window.BACKEND || !inviteId) return null;
  try {
    const res = await window.BACKEND.get("getMyRsvp", { invite_id: inviteId });
    if (res?.ok) return res;
  } catch (e) {
    console.warn("[site] fetchMyRsvp failed", e);
  }
  return null;
}

// Tente de re-soumettre la file d'attente (best-effort, silencieux)
async function flushRsvpQueue() {
  if (!window.BACKEND) return;
  let q;
  try { q = JSON.parse(localStorage.getItem(RSVP_QUEUE_KEY) || "[]"); }
  catch { return; }
  if (!q.length) return;
  const remaining = [];
  for (const item of q) {
    try {
      const { queued_at, ...payload } = item;
      const res = await window.BACKEND.post("submitRsvp", payload);
      if (!res?.ok) remaining.push(item);
    } catch {
      remaining.push(item);
    }
  }
  localStorage.setItem(RSVP_QUEUE_KEY, JSON.stringify(remaining));
}

// Auto-flush au chargement (après 2s pour ne pas bloquer le rendu)
if (typeof window !== "undefined") {
  setTimeout(() => { flushRsvpQueue(); }, 2000);
}

Object.assign(window, {
  useGuestList, submitRsvpToBackend, fetchMyRsvp, enqueueRsvp, flushRsvpQueue,
});
