/* search.jsx — shared search index, command palette, full search page */
(function () {
  const { useState, useEffect, useRef, useMemo } = React;
  const { cx, fmtTime, SmartImg } = window;

  // ---- build a flat searchable index -------------------------------
  function buildIndex() {
    const items = [];
    window.RECIPES.forEach((r) => {
      items.push({
        type: "recipe", slug: r.slug, title: r.title, summary: r.summary,
        image: r.image, category: r.category, total: r.total, difficulty: r.difficulty,
        haystack: [r.title, r.summary, r.category, r.ingredients.map((x) => x.name).join(" ")].join(" ").toLowerCase(),
      });
    });
    window.ARTICLES.forEach((a) => {
      items.push({
        type: "article", slug: a.slug, section: a.section, title: a.title, summary: a.summary,
        haystack: [a.title, a.summary, a.body].join(" ").toLowerCase(),
      });
    });
    return items;
  }
  let _index = null;
  function INDEX() { if (!_index) _index = buildIndex(); return _index; }

  function score(item, q) {
    if (!q) return 0;
    const t = item.title.toLowerCase();
    if (t === q) return 100;
    if (t.startsWith(q)) return 80;
    if (t.includes(q)) return 60;
    if (item.category && item.category.toLowerCase().includes(q)) return 45;
    if (item.summary.toLowerCase().includes(q)) return 30;
    if (item.haystack.includes(q)) return 15;
    return 0;
  }
  function runSearch(q) {
    const query = q.trim().toLowerCase();
    if (!query) return [];
    return INDEX().map((it) => ({ it, s: score(it, query) }))
      .filter((x) => x.s > 0)
      .sort((a, b) => b.s - a.s)
      .map((x) => x.it);
  }

  // ==================================================================
  //  Command palette (⌘K)
  // ==================================================================
  function CommandPalette({ open, onClose, go }) {
    const { Search, ChefHat, Book, Sprout, ArrowRight, Clock } = window.Icons;
    const [q, setQ] = useState("");
    const [active, setActive] = useState(0);
    const inputRef = useRef(null);
    const listRef = useRef(null);

    const results = useMemo(() => runSearch(q), [q]);

    // flat list of actionable rows (quick links when empty, results otherwise)
    const quick = [
      { kind: "nav", label: "Browse all recipes", icon: ChefHat, action: () => go({ name: "section", section: "recipes" }) },
      { kind: "nav", label: "Ingredients", icon: Sprout, action: () => go({ name: "section", section: "ingridients" }) },
      { kind: "nav", label: "Techniques", icon: Book, action: () => go({ name: "section", section: "techniques" }) },
    ];
    const rows = q.trim()
      ? results.map((it) => ({ kind: "result", it, action: () => openItem(it) }))
      : quick;

    function openItem(it) {
      if (it.type === "recipe") go({ name: "recipe", slug: it.slug });
      else go({ name: "article", section: it.section, slug: it.slug });
    }

    useEffect(() => { if (open) { setQ(""); setActive(0); setTimeout(() => inputRef.current && inputRef.current.focus(), 30); } }, [open]);
    useEffect(() => { setActive(0); }, [q]);
    useEffect(() => {
      if (!open) return;
      const onKey = (e) => {
        if (e.key === "Escape") { onClose(); }
        else if (e.key === "ArrowDown") { e.preventDefault(); setActive((a) => Math.min(a + 1, rows.length - 1)); }
        else if (e.key === "ArrowUp") { e.preventDefault(); setActive((a) => Math.max(a - 1, 0)); }
        else if (e.key === "Enter") { e.preventDefault(); const r = rows[active]; if (r) { r.action(); onClose(); } }
      };
      window.addEventListener("keydown", onKey);
      return () => window.removeEventListener("keydown", onKey);
    }, [open, rows, active, onClose]);

    useEffect(() => {
      const el = listRef.current && listRef.current.querySelector('[data-active="true"]');
      if (el) el.scrollIntoView({ block: "nearest" });
    }, [active]);

    if (!open) return null;

    return (
      <div className="overlay" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
        <div className="cmd" role="dialog" aria-modal="true" aria-label="Search">
          <div className="cmd-head">
            <Search size={18} style={{ color: "hsl(var(--muted-foreground))" }} />
            <input ref={inputRef} value={q} onChange={(e) => setQ(e.target.value)}
              placeholder="Search recipes, ingredients, techniques…" />
            <span className="kbd">Esc</span>
          </div>
          <div className="cmd-list" ref={listRef}>
            {!q.trim() && <div className="cmd-group-label">Jump to</div>}
            {q.trim() && <div className="cmd-group-label">{rows.length} result{rows.length === 1 ? "" : "s"}</div>}
            {rows.length === 0 && (
              <div className="cmd-empty">No matches for “{q}”.<br /><span style={{ fontSize: ".84rem" }}>Try “salad”, “sourdough” or “MSG”.</span></div>
            )}
            {rows.map((r, idx) => {
              const isActive = idx === active;
              if (r.kind === "nav") {
                const Ico = r.icon;
                return (
                  <div key={"q" + idx} className="cmd-item" data-active={isActive}
                    onMouseEnter={() => setActive(idx)} onClick={() => { r.action(); onClose(); }}>
                    <span className="ci-ico"><Ico size={18} /></span>
                    <span style={{ flex: 1, fontWeight: 500 }}>{r.label}</span>
                    <ArrowRight size={15} style={{ color: "hsl(var(--muted-foreground))" }} />
                  </div>
                );
              }
              const it = r.it;
              return (
                <div key={it.type + it.slug} className="cmd-item" data-active={isActive}
                  onMouseEnter={() => setActive(idx)} onClick={() => { r.action(); onClose(); }}>
                  <span className="ci-ico">
                    {it.type === "recipe"
                      ? <SmartImg src={it.image} alt="" label="" />
                      : <Book size={18} />}
                  </span>
                  <span style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontWeight: 500, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{it.title}</div>
                    <div className="muted" style={{ fontSize: ".8rem", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>
                      {it.type === "recipe" ? it.category : "Article"} · {it.summary}
                    </div>
                  </span>
                  {it.type === "recipe" && <span className="muted row" style={{ fontSize: ".78rem", gap: ".3rem" }}><Clock size={13} />{fmtTime(it.total)}</span>}
                </div>
              );
            })}
          </div>
          <div className="row" style={{ justifyContent: "space-between", padding: ".55rem .9rem", borderTop: "1px solid hsl(var(--border))", fontSize: ".76rem", color: "hsl(var(--muted-foreground))" }}>
            <span className="row" style={{ gap: ".5rem" }}><span className="kbd">↑↓</span> navigate <span className="kbd">↵</span> open</span>
            <span className="row" style={{ gap: ".35rem" }}>Search by AmosCooks</span>
          </div>
        </div>
      </div>
    );
  }

  // ==================================================================
  //  Full search page
  // ==================================================================
  function SearchPage({ go, initialQ }) {
    const { Search, X } = window.Icons;
    const { RecipeCard, ArticleRow } = window;
    const [q, setQ] = useState(initialQ || "");
    const [filter, setFilter] = useState("all");
    const ref = useRef(null);
    useEffect(() => { ref.current && ref.current.focus(); }, []);

    const all = useMemo(() => runSearch(q), [q]);
    const results = all.filter((it) =>
      filter === "all" ? true : filter === "recipes" ? it.type === "recipe" : it.type === "article");

    const recipes = results.filter((r) => r.type === "recipe");
    const articles = results.filter((r) => r.type === "article");
    const filters = [
      { key: "all", label: "Everything" },
      { key: "recipes", label: "Recipes" },
      { key: "articles", label: "Articles" },
    ];

    return (
      <div className="page container" style={{ paddingTop: "2.4rem", paddingBottom: "4rem" }}>
        <div className="container-tight" style={{ margin: "0 auto", padding: 0 }}>
          <span className="eyebrow">Search</span>
          <h1 className="h1" style={{ margin: ".4rem 0 1.4rem" }}>Find a recipe</h1>
          <div className="input" style={{ height: "3.4rem", fontSize: "1.05rem" }}>
            <Search size={20} />
            <input ref={ref} value={q} onChange={(e) => setQ(e.target.value)} placeholder="Search by name, category or ingredient…" />
            {q && <button className="btn btn-ghost btn-icon btn-sm" onClick={() => setQ("")} aria-label="Clear"><X size={16} /></button>}
          </div>

          <div className="row wrap" style={{ gap: ".5rem", marginTop: "1rem" }}>
            {filters.map((f) => (
              <button key={f.key} className="chip" aria-pressed={filter === f.key} onClick={() => setFilter(f.key)}>{f.label}</button>
            ))}
          </div>
        </div>

        <div style={{ marginTop: "2.2rem" }}>
          {!q.trim() && (
            <div className="muted" style={{ textAlign: "center", padding: "3rem 0" }}>
              Start typing to search {window.RECIPES.length} recipes and {window.ARTICLES.length} articles.
            </div>
          )}
          {q.trim() && results.length === 0 && (
            <div className="muted" style={{ textAlign: "center", padding: "3rem 0" }}>
              No results for “{q}”. Try a different term.
            </div>
          )}

          {recipes.length > 0 && (
            <section style={{ marginBottom: "2.5rem" }}>
              <div className="spread" style={{ marginBottom: "1rem" }}><h2 className="h3">Recipes</h2><span className="muted" style={{ fontSize: ".85rem" }}>{recipes.length}</span></div>
              <div className="grid-recipes stagger">
                {recipes.map((r, idx) => <RecipeCard key={r.slug} recipe={window.RECIPES.find((x) => x.slug === r.slug)} go={go} idx={idx} />)}
              </div>
            </section>
          )}

          {articles.length > 0 && (
            <section>
              <div className="spread" style={{ marginBottom: "1rem" }}><h2 className="h3">Articles</h2><span className="muted" style={{ fontSize: ".85rem" }}>{articles.length}</span></div>
              <div className="col card" style={{ overflow: "hidden" }}>
                {articles.map((a, idx) => <ArticleRow key={a.slug} article={window.ARTICLES.find((x) => x.slug === a.slug)} go={go} last={idx === articles.length - 1} />)}
              </div>
            </section>
          )}
        </div>
      </div>
    );
  }

  Object.assign(window, { CommandPalette, SearchPage, runSearch });
})();
