// CATALOGUE — Filterable gallery of plants
function Catalogue({ setRoute, setPlantId }) {
  const { user } = window.useAuth();
  // Vue (grid | index) : préférence de compte (au login) > localStorage > "grid".
  const [view, setViewState] = React.useState(() => {
    try { return localStorage.getItem("herbier-view") || "grid"; }
    catch { return "grid"; }
  });
  // setView : applique + persiste (localStorage toujours ; compte si connecté).
  const setView = (v) => {
    setViewState(v);
    try { localStorage.setItem("herbier-view", v); } catch {}
    if (user && window.authedFetch) {
      window.authedFetch("/api/me", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ view: v }),
      }).catch(() => { /* best effort : la persistance locale suffit en repli */ });
    }
  };
  const [filterUsage, setFilterUsage] = React.useState(null);
  const [filterFamily, setFilterFamily] = React.useState(null);
  const [filterOrigine, setFilterOrigine] = React.useState(null);
  const [search, setSearch] = React.useState("");
  const [sort, setSort] = React.useState("nom");
  const [indexTick, setIndexTick] = React.useState(0); // re-calcul quand l'index savoirs arrive
  const isMobile = useMobile();

  // Dès qu'on tape, charger (une fois) l'index savoirs pour que la barre
  // trouve aussi composés et propriétés — même matcher que l'overlay.
  React.useEffect(() => {
    if (!search.trim() || window.SEARCH_INDEX || !window.ensureSearchIndex) return;
    window.ensureSearchIndex().then((m) => { if (m) setIndexTick((t) => t + 1); });
  }, [search]);

  // À la connexion, la préférence de vue du compte fait foi (suit l'utilisateur
  // d'un poste à l'autre). Null = aucune préférence → on garde le choix local.
  React.useEffect(() => {
    if (user && user.view) {
      setViewState(user.view);
      try { localStorage.setItem("herbier-view", user.view); } catch {}
    }
  }, [user && user.view]);

  const filtered = React.useMemo(() => {
    // Filtres à facettes (famille / usage / origine) d'abord.
    let list = window.PLANTS.filter((p) => {
      if (filterFamily && p.famille !== filterFamily) return false;
      if (filterUsage) {
        if (filterUsage === "Recette") {
          if (!p.hasRecettes) return false;
        } else {
          const usages = p.usage || (p.medicinal ? ["Médicinal"] : []).concat(p.comestibilite ? ["Comestible"] : []);
          if (!usages.some(u => u.toLowerCase().startsWith(filterUsage.toLowerCase().slice(0,5)))) return false;
        }
      }
      if (filterOrigine) {
        const origines = Array.isArray(p.origine) ? p.origine : [];
        if (!origines.includes(filterOrigine)) return false;
      }
      return true;
    });

    // Recherche texte : on délègue au matcher partagé (accent-insensible,
    // cherche nom/latin/famille/usage). Le résultat est déjà trié par
    // pertinence, donc on ignore le tri alphabétique tant qu'on cherche.
    if (search.trim() && window.searchPlants) {
      return window.searchPlants(search, list).map((r) => r.plant);
    }

    list.sort((a, b) => sort === "nom" ? a.nom.localeCompare(b.nom, "fr") : a.latin.localeCompare(b.latin, "fr"));
    return list;
  }, [search, filterFamily, filterUsage, filterOrigine, sort, indexTick]);

  const goFiche = (id) => { setPlantId(id); setRoute("fiche"); };
  const pad = isMobile ? "0 20px" : "0 40px";

  return (
    <main className="page-enter">
      {/* Header */}
      <section style={{ padding: isMobile ? "44px 0 28px" : "80px 0 40px" }}>
        <div style={{ maxWidth: 1400, margin: "0 auto", padding: pad }}>
          <div className="kicker" style={{ marginBottom: 18 }}>Catalogue · {window.PLANTS.length} espèces consignées</div>
          <h1 className="h-display" style={{ fontSize: isMobile ? "clamp(44px, 10vw, 70px)" : "clamp(64px, 8.5vw, 108px)", lineHeight: 0.95, margin: isMobile ? "0 0 16px" : "0 0 24px", letterSpacing: "-0.02em" }}>
            Recueil <span className="h-italic">complet</span><br/>
            de l'herbier.
          </h1>
          {!isMobile && (
            <p style={{ fontFamily: "var(--serif)", fontSize: 22, lineHeight: 1.5, color: "var(--ink-soft)", maxWidth: 720, margin: "0 0 60px" }}>
              Toutes les fiches du recueil, classées par nom, famille ou usage. Filtrez, comparez, ouvrez chaque fiche pour la lecture détaillée.
            </p>
          )}
        </div>
      </section>

      {/* Toolbar */}
      <section style={{ borderTop: "1px solid var(--line)", borderBottom: "1px solid var(--line)", padding: isMobile ? "16px 0" : "30px 0", background: "var(--tint)" }}>
        <div style={{ maxWidth: 1400, margin: "0 auto", padding: isMobile ? "0 16px" : "0 40px", display: "flex", flexDirection: "column", gap: isMobile ? 14 : 24 }}>
          {/* Recherche + tri */}
          <div style={{ display: "flex", gap: isMobile ? 10 : 24, alignItems: "center", justifyContent: "space-between", flexWrap: isMobile ? "nowrap" : "wrap" }}>
            <div style={{ ...catStyles.searchWrap, flex: "1 1 auto", maxWidth: isMobile ? "none" : 600 }}>
              <IconSearch size={15} />
              <input
                type="text"
                placeholder={isMobile ? "Chercher une plante…" : "Chercher une plante, une famille, un nom latin…"}
                value={search}
                onChange={(e) => setSearch(e.target.value)}
                style={catStyles.searchInput}
              />
            </div>
            {!isMobile && (
              <div style={{ display: "flex", gap: 16, alignItems: "center" }}>
                <span className="kicker">Tri</span>
                <SortBtn active={sort === "nom"} onClick={() => setSort("nom")}>Nom commun</SortBtn>
                <SortBtn active={sort === "latin"} onClick={() => setSort("latin")}>Nom latin</SortBtn>
                <span style={{ width: 1, height: 18, background: "var(--line)" }} />
                <span className="kicker">Vue</span>
                <SortBtn active={view === "grid"} onClick={() => setView("grid")}>Grille</SortBtn>
                <SortBtn active={view === "index"} onClick={() => setView("index")}>Index</SortBtn>
              </div>
            )}
            {isMobile && (
              <div style={{ display: "flex", gap: 6, flexShrink: 0 }}>
                <button onClick={() => setView("grid")} style={{ width: 36, height: 36, border: `1px solid ${view === "grid" ? "var(--ink)" : "var(--line)"}`, background: view === "grid" ? "var(--ink)" : "transparent", display: "grid", placeItems: "center" }} title="Grille">
                  <svg width="14" height="14" viewBox="0 0 14 14" fill={view === "grid" ? "var(--paper)" : "var(--ink-mute)"}>
                    <rect x="0" y="0" width="6" height="6"/><rect x="8" y="0" width="6" height="6"/>
                    <rect x="0" y="8" width="6" height="6"/><rect x="8" y="8" width="6" height="6"/>
                  </svg>
                </button>
                <button onClick={() => setView("index")} style={{ width: 36, height: 36, border: `1px solid ${view === "index" ? "var(--ink)" : "var(--line)"}`, background: view === "index" ? "var(--ink)" : "transparent", display: "grid", placeItems: "center" }} title="Index">
                  <svg width="14" height="10" viewBox="0 0 14 10" fill="none" stroke={view === "index" ? "var(--paper)" : "var(--ink-mute)"} strokeWidth="1.5" strokeLinecap="round">
                    <line x1="0" y1="1" x2="14" y2="1"/><line x1="0" y1="5" x2="14" y2="5"/><line x1="0" y1="9" x2="14" y2="9"/>
                  </svg>
                </button>
              </div>
            )}
          </div>

          {/* Filtres — défilement horizontal sur mobile */}
          <div style={{ overflowX: isMobile ? "auto" : "visible", display: "flex", gap: 10, alignItems: "center", flexWrap: isMobile ? "nowrap" : "wrap", paddingBottom: isMobile ? 4 : 0, scrollbarWidth: "none" }}>
            <span className="kicker" style={{ marginRight: 6, flexShrink: 0 }}>Usage</span>
            <button className={`tag ${filterUsage === null ? "tag-active" : ""}`} style={{ flexShrink: 0 }} onClick={() => setFilterUsage(null)}>Tous</button>
            {window.USAGES.map(u => (
              <button key={u} className={`tag ${filterUsage === u ? "tag-active" : ""}`} style={{ flexShrink: 0 }} onClick={() => setFilterUsage(u === filterUsage ? null : u)}>{u}</button>
            ))}
            <span style={{ width: 1, height: 18, background: "var(--line)", margin: "0 8px", flexShrink: 0 }} />
            <span className="kicker" style={{ marginRight: 6, flexShrink: 0 }}>Origine</span>
            <button className={`tag ${filterOrigine === null ? "tag-active" : ""}`} style={{ flexShrink: 0 }} onClick={() => setFilterOrigine(null)}>Toutes</button>
            {["Sauvage", "Cultivée"].map(o => (
              <button key={o} className={`tag ${filterOrigine === o ? "tag-active" : ""}`} style={{ flexShrink: 0 }} onClick={() => setFilterOrigine(o === filterOrigine ? null : o)}>{o}</button>
            ))}
            <span style={{ width: 1, height: 18, background: "var(--line)", margin: "0 8px", flexShrink: 0 }} />
            <span className="kicker" style={{ marginRight: 6, flexShrink: 0 }}>Famille</span>
            <button className={`tag ${filterFamily === null ? "tag-active" : ""}`} style={{ flexShrink: 0 }} onClick={() => setFilterFamily(null)}>Toutes</button>
            {window.FAMILIES.slice(0, isMobile ? 4 : 6).map(f => (
              <button key={f} className={`tag ${filterFamily === f ? "tag-active" : ""}`} style={{ flexShrink: 0 }} onClick={() => setFilterFamily(f === filterFamily ? null : f)}>{f}</button>
            ))}
          </div>

          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", paddingTop: 4 }}>
            <span style={{ fontFamily: "var(--serif)", fontSize: isMobile ? 15 : 17, fontStyle: "italic", color: "var(--ink-mute)" }}>
              {filtered.length} résultat{filtered.length > 1 ? "s" : ""}
            </span>
            {!isMobile && (
              <span style={{ fontFamily: "var(--mono)", fontSize: 11, letterSpacing: ".18em", color: "var(--ink-mute)", textTransform: "uppercase" }}>
                Mise à jour · 8 mai 2026
              </span>
            )}
          </div>
        </div>
      </section>

      {/* Result */}
      <section style={{ maxWidth: 1400, margin: "40px auto 0", padding: pad }}>
        {view === "grid" ? (
          <div style={{ display: "grid", gridTemplateColumns: isMobile ? "repeat(2, 1fr)" : "repeat(4, 1fr)", gap: isMobile ? 12 : 20 }}>
            {filtered.map((p, i) => (
              <CatCard key={p.id} p={p} idx={i + 1} onClick={() => goFiche(p.id)} isMobile={isMobile} />
            ))}
          </div>
        ) : (
          <div style={{ borderTop: "1px solid var(--line)" }}>
            {filtered.map((p, i) => (
              <IndexRow key={p.id} p={p} idx={i + 1} onClick={() => goFiche(p.id)} />
            ))}
          </div>
        )}
      </section>
    </main>
  );
}

function SortBtn({ children, active, onClick }) {
  return (
    <button onClick={onClick} style={{
      fontFamily: "var(--serif)", fontSize: 15, padding: "6px 0", color: active ? "var(--ink)" : "var(--ink-mute)",
      borderBottom: active ? "1px solid var(--ink)" : "1px solid transparent", borderRadius: 0
    }}>{children}</button>
  );
}

function CatCard({ p, idx, onClick, isMobile }) {
  const [hover, setHover] = React.useState(false);
  const usages = (p.usage || ["Médicinal"]).filter(u => u !== "Symbolique" && u !== "Ornemental");
  return (
    <Reveal>
      <article
        onClick={onClick}
        onMouseEnter={() => setHover(true)}
        onMouseLeave={() => setHover(false)}
        style={catCard}
      >
        <div style={{ position: "relative", overflow: "hidden", borderBottom: "1px solid var(--line-soft)" }}>
          <Plate
            src={p.thumb || null}
            frame={false}
            attribution={p.thumbFromWikipedia ? `https://fr.wikipedia.org/wiki/${encodeURIComponent(p.latin.replace(/ /g,"_"))}` : null}
            label={p.nom.toUpperCase()}
            aspect="4/5"
            style={{ transition: "transform 1100ms var(--ease)", transform: hover ? "scale(1.04)" : "scale(1)" }}
          />
          {!isMobile && (
            <div style={{
              position: "absolute", inset: 0, background: "rgba(28,36,27,0.78)",
              display: "flex", alignItems: "center", justifyContent: "center", color: "#f1ead9",
              opacity: hover ? 1 : 0, transition: "opacity 380ms var(--ease)", padding: 24, textAlign: "center"
            }}>
              <div>
                <div className="kicker" style={{ color: "var(--sand)", marginBottom: 10 }}>Lire la fiche</div>
                <div className="h-italic" style={{ fontSize: 26, marginBottom: 12 }}>{p.latin}</div>
                <IconArrow size={16} />
              </div>
            </div>
          )}
        </div>
        <div style={{ padding: isMobile ? "12px 14px" : "20px 22px" }}>
          <div className="kicker" style={{ marginBottom: 6 }}>{p.famille}</div>
          <h3 className="h-display" style={{ fontSize: isMobile ? 20 : 26, lineHeight: 1.05, margin: "0 0 4px" }}>{p.nom}</h3>
          <div className="h-italic" style={{ fontSize: isMobile ? 13 : 16, color: "var(--moss-deep)", marginBottom: 10 }}>{p.latin}</div>
          {!isMobile && (
            <div style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
              {usages.slice(0,3).map(u => <span key={u} className="tag">{u}</span>)}
            </div>
          )}
        </div>
      </article>
    </Reveal>
  );
}

function IndexRow({ p, idx, onClick }) {
  const [hover, setHover] = React.useState(false);
  const isMobile = useMobile();
  const usages = (p.usage || ["Médicinal"]).filter(u => u !== "Symbolique" && u !== "Ornemental");

  if (isMobile) {
    return (
      <div
        onClick={onClick}
        onTouchStart={() => setHover(true)}
        onTouchEnd={() => setHover(false)}
        style={{
          display: "flex", alignItems: "center", gap: 14,
          padding: "15px 20px", borderBottom: "1px solid var(--line-soft)", cursor: "pointer",
          background: hover ? "rgba(45,67,41,0.04)" : "transparent",
          transition: "background 280ms var(--ease)"
        }}
      >
        <div style={{ flex: 1, minWidth: 0 }}>
          <div className="h-display" style={{ fontSize: 20, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{p.nom}</div>
          <div className="h-italic" style={{ fontSize: 13, color: "var(--moss-deep)" }}>{p.latin}</div>
          <div className="kicker" style={{ marginTop: 2 }}>{p.famille}</div>
        </div>
        <span style={{ color: "var(--ink-mute)", flexShrink: 0 }}>
          <IconArrow size={13} />
        </span>
      </div>
    );
  }

  return (
    <div
      onClick={onClick}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        display: "grid", gridTemplateColumns: "1fr 1.5fr 1fr 1fr 80px",
        padding: "22px 8px", borderBottom: "1px solid var(--line-soft)", alignItems: "center", cursor: "pointer",
        background: hover ? "rgba(45,67,41,0.04)" : "transparent", transition: "background 280ms var(--ease)",
        gap: 24
      }}
    >
      <span className="h-display" style={{ fontSize: 24 }}>{p.nom}</span>
      <span className="h-italic" style={{ fontSize: 18, color: "var(--moss-deep)" }}>{p.latin}</span>
      <span className="kicker">{p.famille}</span>
      <span style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
        {usages.slice(0,2).map(u => <span key={u} className="tag">{u}</span>)}
      </span>
      <span style={{ textAlign: "right", color: hover ? "var(--moss-deep)" : "var(--ink-mute)", transition: "color 280ms var(--ease)" }}>
        <IconArrow size={16} />
      </span>
    </div>
  );
}

const catStyles = {
  searchWrap: { display: "flex", alignItems: "center", gap: 10, padding: "10px 16px", border: "1px solid var(--line)", background: "var(--cream)" },
  searchInput: { flex: 1, border: 0, outline: "none", background: "transparent", fontFamily: "var(--serif)", fontSize: 16, color: "var(--ink)" },
};
const catCard = { cursor: "pointer", background: "var(--cream)", border: "1px solid var(--line-soft)", display: "flex", flexDirection: "column" };

Object.assign(window, { Catalogue });
