// Overlay de recherche global — palette ouvrable par « / » ou la loupe du nav.
// S'appuie sur window.searchPlants (components/search.js). L'état d'ouverture
// est levé dans App (Herbier.html) ; onPick(id) ouvre la fiche.

// Surligne les fragments de `text` qui matchent les termes de `query`, en
// restant accent-insensible. On normalise caractère par caractère pour garder
// l'alignement des index (et gérer les rares décompositions multi-lettres).
function highlightMatch(text, query) {
  const qn = (window.normalizeSearch ? window.normalizeSearch(query) : (query || "").toLowerCase());
  const terms = qn.split(/\s+/).filter(Boolean);
  if (!terms.length || !text) return text;

  const chars = [...String(text)];
  let norm = "";
  const map = []; // map[pos dans norm] = index du caractère d'origine
  chars.forEach((c, ci) => {
    const n = c.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase();
    for (let k = 0; k < n.length; k++) { norm += n[k]; map.push(ci); }
  });

  const mark = new Array(chars.length).fill(false);
  for (const t of terms) {
    let from = 0, idx;
    while ((idx = norm.indexOf(t, from)) !== -1) {
      for (let k = idx; k < idx + t.length; k++) mark[map[k]] = true;
      from = idx + t.length;
    }
  }

  const parts = [];
  let i = 0;
  while (i < chars.length) {
    const m = mark[i];
    let j = i;
    while (j < chars.length && mark[j] === m) j++;
    const piece = chars.slice(i, j).join("");
    parts.push(
      m ? <mark key={i} style={{ background: "rgba(196,154,58,0.30)", color: "inherit", padding: 0 }}>{piece}</mark> : piece
    );
    i = j;
  }
  return parts;
}

// Libellés FR des champs « savoirs » (badge sur les résultats qui matchent
// hors nom/latin/famille/usage — explique pourquoi la plante sort).
const SAVOIR_LABELS = {
  composes: "composés", medicinal: "médicinal", comestibilite: "comestibilité",
  precautions: "précautions", bioindication: "bio-indication",
};

function SearchOverlay({ open, onClose, onPick }) {
  const isMobile = useMobile();
  const [q, setQ] = React.useState("");
  const [sel, setSel] = React.useState(0);
  const [indexTick, setIndexTick] = React.useState(0); // re-calcul quand l'index savoirs arrive
  const inputRef = React.useRef(null);

  const results = React.useMemo(() => {
    if (!open || !q.trim() || !window.searchPlants) return [];
    return window.searchPlants(q, window.PLANTS || []).slice(0, 8);
  }, [q, open, indexTick]);

  // À l'ouverture : reset + focus de l'input + chargement (unique) de l'index savoirs.
  React.useEffect(() => {
    if (!open) return;
    setQ("");
    setSel(0);
    if (window.ensureSearchIndex && !window.SEARCH_INDEX) {
      window.ensureSearchIndex().then((m) => { if (m) setIndexTick((t) => t + 1); });
    }
    const t = setTimeout(() => inputRef.current && inputRef.current.focus(), 30);
    return () => clearTimeout(t);
  }, [open]);

  // La sélection ne doit jamais dépasser la liste courante.
  React.useEffect(() => { setSel(0); }, [q]);

  if (!open) return null;

  const pick = (r) => { if (r) { onPick(r.plant.id); onClose(); } };

  const onKey = (e) => {
    if (e.key === "Escape") { e.preventDefault(); onClose(); }
    else if (e.key === "ArrowDown") { e.preventDefault(); setSel((s) => Math.min(s + 1, results.length - 1)); }
    else if (e.key === "ArrowUp") { e.preventDefault(); setSel((s) => Math.max(s - 1, 0)); }
    else if (e.key === "Enter") { e.preventDefault(); pick(results[sel]); }
  };

  const total = (window.PLANTS || []).length;

  return (
    <div
      onClick={onClose}
      style={{
        position: "fixed", inset: 0, zIndex: 2000,
        background: "rgba(22,24,18,0.45)",
        display: "flex", alignItems: "flex-start", justifyContent: "center",
        padding: isMobile ? "10vh 14px 0" : "12vh 20px 0",
      }}
    >
      <div
        onClick={(e) => e.stopPropagation()}
        role="dialog"
        aria-label="Recherche"
        style={{
          width: "100%", maxWidth: 640, background: "var(--paper)",
          border: "1px solid var(--line)", boxShadow: "0 24px 80px rgba(0,0,0,0.28)",
        }}
      >
        {/* Champ */}
        <div style={{ display: "flex", alignItems: "center", gap: 12, padding: "16px 20px", borderBottom: "1px solid var(--line)" }}>
          <IconSearch size={18} />
          <input
            ref={inputRef}
            type="text"
            value={q}
            onChange={(e) => setQ(e.target.value)}
            onKeyDown={onKey}
            placeholder="Chercher une plante, un nom latin, un usage…"
            style={{ flex: 1, border: 0, outline: "none", background: "transparent", fontFamily: "var(--serif)", fontSize: isMobile ? 17 : 19, color: "var(--ink)" }}
          />
          <kbd style={{ fontFamily: "var(--mono)", fontSize: 10, letterSpacing: ".06em", color: "var(--ink-mute)", border: "1px solid var(--line)", padding: "2px 6px" }}>Échap</kbd>
        </div>

        {/* Résultats */}
        <div style={{ maxHeight: "52vh", overflowY: "auto" }}>
          {!q.trim() && (
            <div style={{ padding: "24px 20px", fontFamily: "var(--serif)", color: "var(--ink-mute)", fontSize: 15, lineHeight: 1.5 }}>
              Tapez pour rechercher parmi {total} fiches — nom, nom latin, famille, usage, mais aussi composés et propriétés (« tanins », « mucilage », « diarrhée »…). Les accents sont optionnels.
            </div>
          )}
          {q.trim() && results.length === 0 && (
            <div style={{ padding: "28px 20px", fontFamily: "var(--serif)", color: "var(--ink-mute)", fontSize: 16 }}>
              Aucune plante trouvée pour « {q.trim()} ».
            </div>
          )}
          {results.map((r, i) => (
            <button
              key={r.plant.id}
              onClick={() => pick(r)}
              onMouseEnter={() => setSel(i)}
              style={{
                display: "flex", alignItems: "center", gap: 14, width: "100%", textAlign: "left",
                padding: "12px 20px", border: 0, borderBottom: "1px solid var(--line-soft)",
                background: i === sel ? "var(--tint)" : "transparent", cursor: "pointer", fontFamily: "inherit",
              }}
            >
              <div style={{ flex: 1, minWidth: 0 }}>
                <div className="h-display" style={{ fontSize: isMobile ? 17 : 19, lineHeight: 1.1, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>
                  {highlightMatch(r.plant.nom, q)}
                </div>
                <div className="h-italic" style={{ fontSize: 13, color: "var(--ink-soft)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>
                  {highlightMatch(r.plant.latin, q)}{r.plant.famille ? " · " + r.plant.famille : ""}
                </div>
              </div>
              {SAVOIR_LABELS[r.field] ? (
                <span style={{ fontFamily: "var(--mono)", fontSize: 9, letterSpacing: ".08em", textTransform: "uppercase", color: "var(--moss-deep)", border: "1px solid var(--moss-deep)", padding: "2px 6px", flexShrink: 0, opacity: 0.85 }}>
                  {SAVOIR_LABELS[r.field]}
                </span>
              ) : (
                Array.isArray(r.plant.usage) && r.plant.usage.length > 0 && (
                  <div style={{ display: "flex", gap: 4, flexShrink: 0 }}>
                    {r.plant.usage.slice(0, 2).map((u) => (
                      <span key={u} style={{ fontFamily: "var(--mono)", fontSize: 9, letterSpacing: ".08em", textTransform: "uppercase", color: "var(--ink-mute)", border: "1px solid var(--line-soft)", padding: "2px 6px" }}>{u}</span>
                    ))}
                  </div>
                )
              )}
            </button>
          ))}
        </div>
      </div>
    </div>
  );
}

window.SearchOverlay = SearchOverlay;
