// app/auth.jsx — Écran d'authentification "fuzzy match" en porte d'entrée
// de l'app invité. 3 variantes visuelles (cinematic, sobre, countdown)
// activables via Tweak.

// Fuzzy match local (même algo que plan-table.jsx)
function authNormalize(s) {
  return (s || "").toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s]/g, "");
}
function authFuzzyMatch(query, list) {
  const q = authNormalize(query).trim();
  if (!q || q.length < 2) return [];
  const qToks = q.split(/\s+/).filter(Boolean);
  return list.map((g) => {
    const n = authNormalize(g.name || "");
    const nToks = n.split(/\s+/);
    let score = 0;
    for (const qt of qToks) {
      for (const nt of nToks) {
        if (nt.startsWith(qt)) score += qt.length / Math.max(nt.length, 1) + 0.5;
        else if (nt.includes(qt)) score += (qt.length / Math.max(nt.length, 1)) * 0.5;
      }
    }
    return { ...g, score };
  }).filter(x => x.score > 0.3).sort((a, b) => b.score - a.score).slice(0, 6);
}

// Construit la liste de candidats à matcher : prend invites backend si dispo
// (avec table/gîte), sinon retombe sur allGuests d'APP_DATA.
function buildAuthCandidates(backend) {
  if (backend?.invites?.length) {
    const tNameById = Object.fromEntries((backend.tables || []).map(t => [t.id, t.name]));
    const gNameById = Object.fromEntries((backend.gites  || []).map(g => [g.id, g.name]));
    return backend.invites.map(inv => ({
      ...inv,
      tableName: inv.tableId ? (tNameById[inv.tableId] || inv.tableId) : null,
      giteName:  inv.giteId  ? (gNameById[inv.giteId]  || inv.giteId)  : null,
    }));
  }
  // Fallback APP_DATA — pas d'id ni rsvp_statut, mais tableId/giteId présents
  const tables = window.APP_DATA?.tables || [];
  const gites  = window.APP_DATA?.gites  || [];
  const list = [];
  tables.forEach(t => (t.guests || []).forEach(name => {
    list.push({ name, tableId: t.id, tableName: t.name, giteId: null, giteName: null });
  }));
  // Compléter avec les occupants des gîtes qui ne sont pas déjà listés
  gites.forEach(g => (g.occupants || []).forEach(name => {
    const ex = list.find(x => x.name === name);
    if (ex) { ex.giteId = g.id; ex.giteName = g.name; }
    else    list.push({ name, tableId: null, tableName: null, giteId: g.id, giteName: g.name });
  }));
  return list;
}

// ─────────────────────────────────────────────────────────
// AuthGate — wrapper qui affiche AuthScreen si non identifié
// ─────────────────────────────────────────────────────────
function AuthGate({ variant = "cinematic", children }) {
  const { identity } = useGuest();
  if (!identity) return <AuthScreen variant={variant} />;
  return children;
}

// ─────────────────────────────────────────────────────────
// AuthScreen — l'écran lui-même, dispatch sur la variante
// ─────────────────────────────────────────────────────────
function AuthScreen({ variant = "cinematic" }) {
  const { login } = useGuest();
  const backend = useAppBackend();
  const candidates = React.useMemo(() => buildAuthCandidates(backend), [backend]);

  const [query, setQuery] = React.useState("");
  const [manualMode, setManualMode] = React.useState(false);
  const matches = React.useMemo(() => authFuzzyMatch(query, candidates), [query, candidates]);

  const handleSelectMatch = (match) => {
    const id = identityFromInvite(match);
    if (id) login(id);
  };
  const handleManualSubmit = () => {
    const id = identityFromManual(query);
    if (id) login(id);
  };

  // Dispatch variante visuelle
  if (variant === "sobre")     return <AuthSobre        {...{ query, setQuery, matches, candidates, manualMode, setManualMode, onSelect: handleSelectMatch, onManualSubmit: handleManualSubmit }} />;
  if (variant === "countdown") return <AuthCountdown    {...{ query, setQuery, matches, candidates, manualMode, setManualMode, onSelect: handleSelectMatch, onManualSubmit: handleManualSubmit }} />;
  return                              <AuthCinematic   {...{ query, setQuery, matches, candidates, manualMode, setManualMode, onSelect: handleSelectMatch, onManualSubmit: handleManualSubmit }} />;
}

// ─────────────────────────────────────────────────────────
// Bloc de résultats partagé entre les 3 variantes
// ─────────────────────────────────────────────────────────
function AuthMatches({ query, matches, candidates, manualMode, setManualMode, onSelect, onManualSubmit, dark = false }) {
  const fg     = dark ? "rgba(255,255,255,0.95)" : A.ink;
  const fgSoft = dark ? "rgba(255,255,255,0.65)" : A.inkSoft;
  const fgMute = dark ? "rgba(255,255,255,0.40)" : A.inkMute;
  const bgRow  = dark ? "rgba(255,255,255,0.05)" : A.white;
  const bgRowHover = dark ? "rgba(190,154,72,0.15)" : A.paper;
  const border = dark ? "rgba(255,255,255,0.12)" : A.ruleSoft;
  const accent = A.or;

  const showNotFound = query.length >= 2 && matches.length === 0 && !manualMode && candidates.length > 0;
  const rsvpNotOui = (m) => m.rsvp_statut && m.rsvp_statut !== "oui";

  if (manualMode) {
    return (
      <div style={{ marginTop: 12, padding: 18,
        background: dark ? "rgba(0,0,0,0.35)" : A.paper, border: `1px solid ${border}`,
      }}>
        <div style={{ fontFamily: A.mono, fontSize: 10, letterSpacing: 2.5, color: accent, textTransform: "uppercase", fontWeight: 600 }}>
          ★ Mode invité libre
        </div>
        <div style={{ marginTop: 8, fontFamily: A.italic, fontStyle: "italic", fontSize: 14, color: fgSoft, lineHeight: 1.5 }}>
          On ne vous trouve pas dans la liste, pas de souci.
          Tapez votre prénom et nom — on prend bonne note et on adapte au mariage.
        </div>
        <div style={{ marginTop: 14, display: "flex", gap: 8 }}>
          <button
            onClick={onManualSubmit}
            disabled={query.trim().length < 2}
            style={{
              flex: 1, padding: "14px 18px",
              background: query.trim().length < 2 ? (dark ? "rgba(255,255,255,0.1)" : A.ruleSoft) : A.rouge,
              color: query.trim().length < 2 ? fgMute : A.white,
              border: "none", cursor: query.trim().length < 2 ? "not-allowed" : "pointer",
              fontFamily: A.mono, fontSize: 11, letterSpacing: 2.5, textTransform: "uppercase", fontWeight: 600,
            }}>
            ♥ Continuer en tant que "{query.trim() || "…"}"
          </button>
          <button onClick={() => setManualMode(false)} style={{
            padding: "14px 18px", background: "transparent",
            color: fgSoft, border: `1.5px solid ${border}`, cursor: "pointer",
            fontFamily: A.mono, fontSize: 11, letterSpacing: 2.5, textTransform: "uppercase", fontWeight: 600,
          }}>← Annuler</button>
        </div>
      </div>
    );
  }

  if (!matches.length && !showNotFound) return null;

  return (
    <div style={{ marginTop: 12 }}>
      {matches.length > 0 && (
        <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
          {matches.map((m, i) => {
            const notConfirmed = rsvpNotOui(m);
            return (
              <button key={m.id || m.name + i} onClick={() => onSelect(m)} style={{
                textAlign: "left", padding: "14px 16px",
                background: bgRow, border: `1px solid ${border}`,
                cursor: "pointer", display: "flex", alignItems: "center", gap: 12,
                transition: "all .15s",
              }}
                onMouseEnter={(e) => e.currentTarget.style.background = bgRowHover}
                onMouseLeave={(e) => e.currentTarget.style.background = bgRow}
              >
                <div style={{
                  width: 36, height: 36, borderRadius: "50%",
                  background: accent + "22", border: `1.5px solid ${accent}`,
                  color: accent, fontFamily: A.display, fontSize: 14, fontWeight: 700,
                  display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0,
                }}>{(m.name || "?").trim()[0]?.toUpperCase() || "?"}</div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontFamily: A.display, fontWeight: 700, fontSize: 17, color: fg, lineHeight: 1.1 }}>
                    {m.name}
                  </div>
                  <div style={{ fontFamily: A.mono, fontSize: 9, letterSpacing: 1.5, color: fgMute, textTransform: "uppercase", marginTop: 3 }}>
                    {m.tableName ? `♦ ${m.tableName}` : "Pas encore placé·e"}
                    {m.giteName ? ` · ♣ ${m.giteName}` : ""}
                  </div>
                </div>
                <div style={{ color: accent, fontFamily: A.display, fontSize: 20, flexShrink: 0 }}>→</div>
              </button>
            );
          })}
          {/* Avertissement RSVP non-confirmé sur le 1er match */}
          {matches[0] && rsvpNotOui(matches[0]) && (
            <div style={{
              marginTop: 8, padding: "10px 14px",
              background: A.rougePale, border: `1px solid ${A.rouge}`,
              fontFamily: A.italic, fontStyle: "italic", fontSize: 12, color: dark ? A.rouge : A.rougeDeep, lineHeight: 1.4,
            }}>
              On a hâte de vous voir — pensez à <strong style={{ fontStyle: "normal" }}>confirmer votre présence</strong> sur le site avant !
            </div>
          )}
        </div>
      )}

      {showNotFound && (
        <div style={{ marginTop: 10, padding: 14, background: dark ? "rgba(0,0,0,0.35)" : A.rougePale, border: `1px solid ${A.rouge}` }}>
          <div style={{ fontFamily: A.italic, fontStyle: "italic", fontSize: 13, color: dark ? "rgba(255,255,255,0.85)" : A.rougeDeep, lineHeight: 1.45 }}>
            Aucune correspondance dans notre liste. Faute de frappe ? +1 ? Invité de dernière minute ?
          </div>
          <button onClick={() => setManualMode(true)} style={{
            marginTop: 10, padding: "9px 14px",
            background: A.rouge, color: A.white, border: "none",
            fontFamily: A.mono, fontSize: 10, letterSpacing: 2, textTransform: "uppercase", fontWeight: 600, cursor: "pointer",
          }}>★ Je suis quand même invité·e</button>
        </div>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────
// VARIANTE 1 — Cinematic (full-screen, image, grosse typo)
// ─────────────────────────────────────────────────────────
function AuthCinematic(p) {
  return (
    <div style={{
      minHeight: "100vh", background: A.ink, color: A.white,
      display: "flex", flexDirection: "column", position: "relative", overflow: "hidden",
    }}>
      {/* Wash de fond */}
      <div style={{ position: "absolute", inset: 0, opacity: 0.32, pointerEvents: "none" }}>
        <img src="assets/wc-strokes.jpg" alt=""
          style={{ width: "100%", height: "100%", objectFit: "cover", filter: "hue-rotate(0deg) saturate(0.7) brightness(0.7)" }}/>
      </div>
      <div style={{ position: "absolute", inset: 0, background: `radial-gradient(ellipse at center top, transparent 0%, ${A.ink} 80%)`, pointerEvents: "none" }}/>

      {/* Header */}
      <div style={{ position: "relative", padding: "44px 24px 0", textAlign: "center" }}>
        <div style={{ fontFamily: A.mono, fontSize: 9, letterSpacing: 5, color: A.or, textTransform: "uppercase", animation: "a-up .6s ease both" }}>
          ♥ App invité · 21 / 08 / 2027
        </div>
        <div style={{
          marginTop: 22,
          fontFamily: A.display, fontStyle: "italic", fontSize: "clamp(54px, 14vw, 88px)",
          fontWeight: 700, color: A.white, lineHeight: 0.92, letterSpacing: -2,
          animation: "a-up .6s .1s ease both",
        }}>
          Enora <span style={{ color: A.or }}>&amp;</span><br/>Antoine
        </div>
        <div style={{
          marginTop: 24, maxWidth: 380, margin: "24px auto 0",
          fontFamily: A.italic, fontStyle: "italic", fontSize: 18,
          color: "rgba(255,255,255,0.78)", lineHeight: 1.5,
          animation: "a-up .6s .2s ease both",
        }}>
          Pour commencer, qui êtes-vous ?
          On retrouve votre tablée, votre gîte, et on garde votre identité pour le reste de l'app.
        </div>
      </div>

      {/* Search */}
      <div style={{ position: "relative", padding: "32px 24px 60px", flex: 1, maxWidth: 540, margin: "0 auto", width: "100%", animation: "a-up .6s .3s ease both" }}>
        <div style={{ position: "relative" }}>
          <input
            type="text" value={p.query} onChange={(e) => p.setQuery(e.target.value)}
            placeholder={p.manualMode ? "Prénom Nom (saisie libre)…" : "Tapez votre prénom et nom…"}
            autoFocus
            style={{
              width: "100%", padding: "18px 22px",
              background: "rgba(255,255,255,0.06)",
              border: `1.5px solid ${p.query ? A.or : "rgba(255,255,255,0.22)"}`,
              color: A.white, fontFamily: A.display, fontStyle: "italic", fontWeight: 400,
              fontSize: 20, outline: "none", letterSpacing: -0.3,
            }}
          />
        </div>

        <AuthMatches {...p} dark={true} />

        {/* Pied : disclaimer + lien fallback */}
        <div style={{ marginTop: 28, textAlign: "center" }}>
          {!p.manualMode && (
            <button onClick={() => p.setManualMode(true)} style={{
              background: "transparent", border: "none", color: "rgba(255,255,255,0.55)",
              fontFamily: A.italic, fontStyle: "italic", fontSize: 14, cursor: "pointer",
              textDecoration: "underline", textUnderlineOffset: 4,
            }}>
              Pas dans la liste ? Cliquez ici
            </button>
          )}
          <div style={{
            marginTop: 18, fontFamily: A.mono, fontSize: 9, letterSpacing: 2, color: "rgba(255,255,255,0.35)", textTransform: "uppercase",
          }}>
            ♣ Vos infos restent dans votre navigateur ♣
          </div>
        </div>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────
// VARIANTE 2 — Sobre (clair, fonctionnel)
// ─────────────────────────────────────────────────────────
function AuthSobre(p) {
  return (
    <div style={{ minHeight: "100vh", background: A.paper, display: "flex", flexDirection: "column" }}>
      <AppTopBanner />
      <div style={{ flex: 1, padding: "40px 20px 60px", maxWidth: 540, width: "100%", margin: "0 auto" }}>
        <div style={{ textAlign: "center" }}>
          <div className="eyebrow">♥ Bienvenue</div>
          <div className="display-bold" style={{ fontSize: "clamp(34px, 8vw, 46px)", color: A.ink, marginTop: 14, letterSpacing: -1 }}>
            Identifiez-vous
          </div>
          <div style={{ width: 40, height: 2, background: A.or, margin: "16px auto 0" }} />
          <div style={{ marginTop: 18, fontFamily: A.italic, fontStyle: "italic", fontSize: 16, color: A.inkSoft, lineHeight: 1.55, maxWidth: 420, margin: "18px auto 0" }}>
            On a besoin de savoir qui vous êtes pour vous retrouver dans la liste — votre table, votre gîte, et pour signer vos messages.
          </div>
        </div>

        <div style={{ marginTop: 36 }}>
          <label style={{ display: "block", fontFamily: A.mono, fontSize: 10, letterSpacing: 2.5, color: A.inkMute, textTransform: "uppercase", marginBottom: 8 }}>
            ♦ Prénom et Nom
          </label>
          <input
            type="text" value={p.query} onChange={(e) => p.setQuery(e.target.value)}
            placeholder="Camille Martin"
            autoFocus
            style={{
              width: "100%", padding: "16px 18px",
              background: A.white, border: `1.5px solid ${p.query ? A.or : A.rule}`,
              fontFamily: A.sans, fontSize: 17, color: A.ink, outline: "none",
            }}
          />
        </div>

        <AuthMatches {...p} dark={false} />

        {!p.manualMode && (
          <div style={{ marginTop: 30, textAlign: "center" }}>
            <button onClick={() => p.setManualMode(true)} style={{
              background: "transparent", border: "none", color: A.inkSoft,
              fontFamily: A.italic, fontStyle: "italic", fontSize: 14, cursor: "pointer",
              textDecoration: "underline", textUnderlineOffset: 4,
            }}>
              Pas dans la liste ? Continuer quand même →
            </button>
          </div>
        )}

        <div style={{ marginTop: 40, padding: "14px 18px", background: A.white, border: `1px solid ${A.ruleSoft}`, fontFamily: A.italic, fontStyle: "italic", fontSize: 12, color: A.inkMute, textAlign: "center", lineHeight: 1.5 }}>
          Vos infos restent dans votre navigateur. On vous redemandera votre identité tous les {IDENTITY_TTL_DAYS} jours environ.
        </div>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────
// VARIANTE 3 — Countdown (avec compte-à-rebours)
// ─────────────────────────────────────────────────────────
function AuthCountdown(p) {
  const cd = useCountdownA(APP_DATA.dateISO);
  return (
    <div style={{ minHeight: "100vh", background: A.paper, display: "flex", flexDirection: "column", position: "relative", overflow: "hidden" }}>
      <WashBg hue={30} opacity={0.18}/>
      <div style={{ position: "relative", flex: 1, padding: "32px 20px 40px", maxWidth: 560, width: "100%", margin: "0 auto" }}>
        {/* Bandeau date */}
        <div style={{ textAlign: "center", animation: "a-up .5s ease both" }}>
          <div style={{ fontFamily: A.mono, fontSize: 10, letterSpacing: 4, color: A.or, textTransform: "uppercase" }}>
            ♥ Enora &amp; Antoine
          </div>
          <div style={{ marginTop: 12, fontFamily: A.display, fontWeight: 700, fontSize: "clamp(38px, 9vw, 52px)", color: A.ink, lineHeight: 0.95, letterSpacing: -1 }}>
            App des invités
          </div>
        </div>

        {/* Countdown */}
        <div style={{ marginTop: 30, padding: "18px 16px", background: A.ink, color: A.white, animation: "a-up .5s .1s ease both" }}>
          <div style={{ fontFamily: A.mono, fontSize: 9, letterSpacing: 3, color: A.or, textAlign: "center", textTransform: "uppercase", marginBottom: 10 }}>
            Plus que
          </div>
          <div style={{ display: "flex", justifyContent: "space-between", gap: 6, fontVariantNumeric: "tabular-nums" }}>
            {[{v:cd.d,l:"jours"},{v:cd.h,l:"h"},{v:cd.m,l:"min"},{v:cd.s,l:"s"}].map(x => (
              <div key={x.l} style={{ flex: 1, textAlign: "center" }}>
                <div style={{ fontFamily: A.display, fontWeight: 700, fontSize: 28, lineHeight: 1, color: A.or }}>{String(x.v).padStart(2,"0")}</div>
                <div style={{ fontFamily: A.mono, fontSize: 7.5, opacity: 0.7, letterSpacing: 2, marginTop: 4, textTransform: "uppercase" }}>{x.l}</div>
              </div>
            ))}
          </div>
        </div>

        {/* Identification */}
        <div style={{ marginTop: 30, animation: "a-up .5s .2s ease both" }}>
          <div style={{ textAlign: "center", marginBottom: 14 }}>
            <div className="eyebrow" style={{ color: A.rouge }}>♥ Pour entrer dans l'app</div>
            <div style={{ marginTop: 10, fontFamily: A.display, fontWeight: 700, fontSize: 26, color: A.ink, lineHeight: 1.1, letterSpacing: -0.5 }}>
              Qui êtes-vous ?
            </div>
            <div style={{ marginTop: 8, fontFamily: A.italic, fontStyle: "italic", fontSize: 14, color: A.inkSoft, lineHeight: 1.5, maxWidth: 360, margin: "8px auto 0" }}>
              On vous retrouve dans la liste — table, gîte, et pour signer vos messages au fil de l'app.
            </div>
          </div>
          <input
            type="text" value={p.query} onChange={(e) => p.setQuery(e.target.value)}
            placeholder={p.manualMode ? "Prénom Nom (saisie libre)…" : "Tapez votre prénom et nom…"}
            autoFocus
            style={{
              width: "100%", padding: "16px 18px",
              background: A.white, border: `1.5px solid ${p.query ? A.or : A.rule}`,
              fontFamily: A.sans, fontSize: 16, color: A.ink, outline: "none",
            }}
          />

          <AuthMatches {...p} dark={false} />

          {!p.manualMode && (
            <div style={{ marginTop: 22, textAlign: "center" }}>
              <button onClick={() => p.setManualMode(true)} style={{
                background: "transparent", border: "none", color: A.inkSoft,
                fontFamily: A.italic, fontStyle: "italic", fontSize: 14, cursor: "pointer",
                textDecoration: "underline", textUnderlineOffset: 4,
              }}>
                Je ne suis pas dans la liste
              </button>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { AuthGate, AuthScreen, AuthCinematic, AuthSobre, AuthCountdown });
