// admin-app/components.jsx — Composants partagés de l'admin

// ─── Loading spinner inline ──────────────────────────────────────────
function AdSpinner({ size = 16 }) {
  return (
    <span style={{
      display: "inline-block",
      width: size, height: size,
      border: `2px solid ${AD.ruleSoft}`, borderTopColor: AD.or,
      borderRadius: "50%",
      animation: "ad-spin .8s linear infinite",
    }}/>
  );
}
if (typeof document !== "undefined" && !document.getElementById("ad-spin-style")) {
  const s = document.createElement("style");
  s.id = "ad-spin-style";
  s.textContent = `@keyframes ad-spin { to { transform: rotate(360deg); } }`;
  document.head.appendChild(s);
}

// ─── Page section (header + content) ─────────────────────────────────
function AdPage({ title, eyebrow, actions, children }) {
  return (
    <div className="ad-up" style={{ padding: "0" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 18, paddingBottom: 12, borderBottom: `1px solid ${AD.ruleSoft}` }}>
        <div>
          {eyebrow && <div className="eyebrow" style={{ marginBottom: 4 }}>{eyebrow}</div>}
          <div className="display-bold" style={{ fontSize: 26, color: AD.ink }}>{title}</div>
        </div>
        {actions && <div style={{ display: "flex", gap: 8 }}>{actions}</div>}
      </div>
      {children}
    </div>
  );
}

// ─── Card avec accent or sur le bord gauche ──────────────────────────
function AdCard({ accent = AD.or, children, style = {} }) {
  return (
    <div style={{
      background: AD.white, padding: "16px 18px",
      border: `1px solid ${AD.ruleSoft}`,
      borderLeft: `3px solid ${accent}`,
      ...style,
    }}>{children}</div>
  );
}

// ─── Pill / badge ────────────────────────────────────────────────────
function AdPill({ children, color = "ink", small }) {
  const colors = {
    ink:    { bg: AD.paperDeep, fg: AD.ink },
    or:     { bg: AD.orPale, fg: AD.orDeep },
    rouge:  { bg: AD.rougePale, fg: AD.rougeDeep },
    sage:   { bg: AD.sagePale, fg: AD.sage },
    mute:   { bg: AD.paperDeep, fg: AD.inkMute },
  };
  const c = colors[color] || colors.ink;
  return (
    <span style={{
      display: "inline-block",
      padding: small ? "2px 7px" : "3px 10px",
      background: c.bg, color: c.fg,
      fontFamily: AD.mono, fontSize: small ? 8 : 9, letterSpacing: 1.2,
      textTransform: "uppercase", fontWeight: 600,
    }}>{children}</span>
  );
}

// ─── Affichage prénom + initiale nom (gère homonymes) ────────────────
function displayName(invite, allInvites = []) {
  if (!invite) return "—";
  const prenom = invite.prenom || "";
  if (!prenom) return "?";
  // Compte les homonymes (même prénom)
  const homonymes = allInvites.filter(i => (i.prenom || "").toLowerCase() === prenom.toLowerCase() && i.rsvp_statut !== "non");
  if (homonymes.length <= 1) return prenom;
  // Affiche prénom + initiale du nom
  const initiale = (invite.nom || "").charAt(0).toUpperCase();
  return initiale ? `${prenom} ${initiale}.` : prenom;
}

// ─── Hook : recharge automatique des données ─────────────────────────
function useAdminData() {
  const [data, setData] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const [refreshing, setRefreshing] = React.useState(false);
  const [lastFetch, setLastFetch] = React.useState(null);

  const reload = React.useCallback(async (silent = false) => {
    if (silent) setRefreshing(true); else setLoading(true);
    try {
      const res = await adminGetAll();
      if (res?.ok) {
        setData(res);
        setError(null);
        setLastFetch(new Date());
      } else {
        setError(res?.error || "Erreur inconnue");
      }
    } catch (e) {
      setError(e.message);
    } finally {
      setLoading(false);
      setRefreshing(false);
    }
  }, []);

  React.useEffect(() => { reload(); }, [reload]);

  // Auto-refresh toutes les 60 s (silent) — sauf si une op admin est en cours
  // (cf. window.__adminFreezeRefresh, utilisé par les modals des pages édition)
  React.useEffect(() => {
    const id = setInterval(() => {
      if (window.__adminFreezeRefresh) return;
      reload(true);
    }, 60000);
    return () => clearInterval(id);
  }, [reload]);

  return { data, loading, refreshing, error, lastFetch, reload };
}

// ─── Fuzzy include (recherche tolerante) ─────────────────────────────
function normalize(s) {
  return (s || "").toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
}
function fuzzyMatch(needle, haystack) {
  return normalize(haystack).includes(normalize(needle));
}

// ─── Bandeau sticky bas pour sauvegarder un batch (Tables / Gîtes / …) ─
// Utilisé par les pages qui collectent des modifs localement et les envoient
// via un seul appel bulkAssign.
function AdSaveBar({ count, saving, err, onSave, onCancel, label = "Modification" }) {
  return (
    <div style={{
      position: "fixed", left: 0, right: 0, bottom: 0, zIndex: 200,
      background: AD.ink, color: AD.white,
      padding: "14px 28px",
      display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16,
      boxShadow: "0 -4px 18px rgba(0,0,0,0.18)",
      borderTop: `3px solid ${AD.or}`,
    }}>
      <div style={{ display: "flex", alignItems: "center", gap: 14, minWidth: 0 }}>
        <span style={{ fontFamily: AD.display, fontWeight: 700, fontSize: 22, color: AD.or, lineHeight: 1 }}>{count}</span>
        <div style={{ minWidth: 0 }}>
          <div style={{ fontFamily: AD.mono, fontSize: 10, letterSpacing: 1.5, color: AD.or, textTransform: "uppercase", fontWeight: 600 }}>
            {label}{count > 1 ? "s" : ""} en attente
          </div>
          <div style={{ fontFamily: AD.italic, fontStyle: "italic", fontSize: 12, color: "rgba(255,255,255,0.65)", marginTop: 2 }}>
            {err
              ? <span style={{ color: AD.rouge }}>⚠ {err}</span>
              : (saving ? "Envoi au Sheet…" : "Les changements ne sont pas encore dans le Google Sheet.")}
          </div>
        </div>
      </div>
      <div style={{ display: "flex", gap: 8, flexShrink: 0 }}>
        <button className="btn" onClick={onCancel} disabled={saving}
          style={{ background: "transparent", color: "rgba(255,255,255,0.85)", borderColor: "rgba(255,255,255,0.3)" }}>
          ✗ Annuler
        </button>
        <button className="btn gold" onClick={onSave} disabled={saving}>
          {saving ? <><AdSpinner size={10}/> Sauvegarde…</> : <>✓ Sauvegarder dans le Sheet</>}
        </button>
      </div>
    </div>
  );
}

Object.assign(window, {
  AdSpinner, AdPage, AdCard, AdPill, AdSaveBar,
  displayName, useAdminData,
  normalize, fuzzyMatch,
});
