/* ============================================================
   AfricaMart — Browse / Search + Suppliers directory
   ============================================================ */
const PAGE_SIZE = 24;

function BrowsePage({ nav, currency, params }) {
  // ── Filter state ───────────────────────────────────────────
  const [q,            setQ]            = useState(params.q || "");
  const [cat,          setCat]          = useState(params.cat || "");
  const [country,      setCountry]      = useState(params.country || "");
  const [verifiedOnly, setVerifiedOnly] = useState(false);
  const [maxMoq,       setMaxMoq]       = useState(0);
  const [maxPrice,     setMaxPrice]     = useState(0);
  const [sort,         setSort]         = useState("relevance");

  // ── Server-side pagination state ───────────────────────────
  const [page,          setPage]         = useState(1);
  const [serverResults, setServerResults]= useState(null); // null → use client-side fallback
  const [total,         setTotal]        = useState(0);
  const [loading,       setLoading]      = useState(false);
  const fetchIdRef = useRef(0);

  // Sync URL params when they change externally (e.g. category click on home page)
  useEffect(() => {
    setQ(params.q || "");
    setCat(params.cat || "");
    setCountry(params.country || "");
  }, [params.q, params.cat, params.country]);

  // Reset to page 1 whenever any filter changes
  useEffect(() => { setPage(1); }, [q, cat, country, verifiedOnly, maxMoq, maxPrice, sort]);

  // Server-side fetch — fires on any filter or page change
  useEffect(() => {
    if (!window.supabaseClient || !window.DB || !DB.searchProducts) return;

    const id = ++fetchIdRef.current;
    setLoading(true);

    // Debounce text search; instant for other filters
    const delay = q.trim().length > 0 ? 500 : 0;
    const timer = setTimeout(async () => {
      try {
        const { products, total: t } = await DB.searchProducts({
          q: q.trim(), cat, country, verifiedOnly,
          maxPrice, maxMoq, sort, page, pageSize: PAGE_SIZE,
        });
        if (id !== fetchIdRef.current) return;
        setServerResults(products);
        setTotal(t);
      } catch (e) {
        if (id !== fetchIdRef.current) return;
        // Fall back to client-side on error
        setServerResults(null);
        console.warn("[AfricaMart] searchProducts error, using local data:", e.message);
      } finally {
        if (id === fetchIdRef.current) setLoading(false);
      }
    }, delay);

    return () => clearTimeout(timer);
  }, [q, cat, country, verifiedOnly, maxMoq, maxPrice, sort, page]);

  // ── Client-side fallback (no Supabase, or on fetch error) ──
  const localResults = useMemo(() => {
    if (serverResults !== null) return [];
    let r = AM.PRODUCTS.filter(p => {
      const s = AM.supplierById[p.supplier];
      if (!s) return false;
      if (cat && p.cat !== cat) return false;
      if (country && s.country !== country) return false;
      if (verifiedOnly && !s.verified) return false;
      if (maxMoq && p.moq > maxMoq) return false;
      if (maxPrice && p.priceUSD > maxPrice) return false;
      if (q) {
        const hay = (p.name + " " + (p.tags || []).join(" ") + " " + s.name).toLowerCase();
        if (!hay.includes(q.toLowerCase())) return false;
      }
      return true;
    });
    if (sort === "newest")     r = [...r].reverse();
    if (sort === "inquired")   r = [...r].sort((a, b) => b.inquiries - a.inquiries);
    if (sort === "price_asc")  r = [...r].sort((a, b) => a.priceUSD - b.priceUSD);
    if (sort === "price_desc") r = [...r].sort((a, b) => b.priceUSD - a.priceUSD);
    return r;
  }, [serverResults, q, cat, country, verifiedOnly, maxMoq, maxPrice, sort]);

  const displayResults = serverResults !== null ? serverResults : localResults;
  const displayTotal   = serverResults !== null ? total : localResults.length;
  const totalPages     = Math.max(1, Math.ceil(displayTotal / PAGE_SIZE));

  const clearAll = () => {
    setQ(""); setCat(""); setCountry(""); setVerifiedOnly(false); setMaxMoq(0); setMaxPrice(0);
  };
  const activeFilters = [
    cat && AM.catById[cat] && AM.catById[cat].name,
    country && AM.countryByCode[country] && AM.countryByCode[country].name,
    verifiedOnly && "Verified only",
    maxMoq   > 0 && "MOQ ≤ " + maxMoq,
    maxPrice > 0 && "≤ $" + maxPrice,
  ].filter(Boolean);

  return (
    <div className="route-anim wrap" style={{ padding: "28px 24px 64px" }}>
      <Breadcrumb nav={nav} trail={[["Home", () => nav("home")], ["Browse products"]]} />

      {/* Search row */}
      <div style={{ display: "flex", gap: 10, marginTop: 14, flexWrap: "wrap" }}>
        <div style={{ flex: 1, minWidth: 240, display: "flex", alignItems: "center", gap: 10, background: "#fff", border: "1px solid var(--border-strong)", borderRadius: 10, padding: "0 14px" }}>
          <Icon name={loading ? "loader-circle" : "search"} size={18} className={loading ? "spin" : ""}
            style={{ color: loading ? "var(--gold-600)" : "var(--ink-400)", flexShrink: 0 }} />
          <input value={q} onChange={e => setQ(e.target.value)} placeholder="Search products & suppliers…"
            style={{ border: "none", outline: "none", flex: 1, padding: "12px 0", fontSize: 15 }} />
          {q && <a onClick={() => setQ("")} style={{ cursor: "pointer", color: "var(--ink-400)", lineHeight: 1 }}>
            <Icon name="x" size={16} />
          </a>}
        </div>
        <select className="select" value={sort} onChange={e => setSort(e.target.value)} style={{ width: "auto", fontWeight: 600 }}>
          <option value="relevance">Sort: Relevance</option>
          <option value="newest">Sort: Newest</option>
          <option value="inquired">Sort: Most inquired</option>
          <option value="price_asc">Sort: Price ↑</option>
          <option value="price_desc">Sort: Price ↓</option>
        </select>
      </div>

      {/* AI smart matching */}
      {q && <AIMatch query={q} nav={nav} cur={currency} />}

      <div className="browse-layout" style={{ display: "grid", gridTemplateColumns: "260px 1fr", gap: 28, marginTop: 22, alignItems: "start" }}>
        {/* Filters sidebar */}
        <aside className="card filter-rail" style={{ padding: 20, position: "sticky", top: 84 }}>
          <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 6 }}>
            <b style={{ fontSize: 15 }}>Filters</b>
            {activeFilters.length > 0 && <a onClick={clearAll} style={{ cursor: "pointer", fontSize: 13, color: "var(--navy-600)", fontWeight: 600 }}>Clear</a>}
          </div>
          <FilterGroup title="Category">
            {AM.CATEGORIES.slice(0, 7).map(c => (
              <RadioRow key={c.id} checked={cat === c.id} onClick={() => setCat(cat === c.id ? "" : c.id)} label={c.name} count={c.count} />
            ))}
          </FilterGroup>
          <FilterGroup title="Country">
            {AM.COUNTRIES.slice(0, 6).map(c => (
              <RadioRow key={c.code} checked={country === c.code} onClick={() => setCountry(country === c.code ? "" : c.code)}
                label={<span style={{ display: "inline-flex", alignItems: "center", gap: 7 }}><Flag code={c.code} size={13} /> {c.name}</span>} />
            ))}
          </FilterGroup>
          <FilterGroup title="Verification">
            <label style={{ display: "flex", alignItems: "center", gap: 9, cursor: "pointer", fontSize: 14, padding: "5px 0" }}>
              <input type="checkbox" checked={verifiedOnly} onChange={e => setVerifiedOnly(e.target.checked)} style={{ width: 16, height: 16, accentColor: "var(--navy-700)" }} />
              Verified suppliers only
            </label>
          </FilterGroup>
          <FilterGroup title={"Max MOQ" + (maxMoq ? ": " + maxMoq : "")}>
            <input type="range" min="0" max="1000" step="50" value={maxMoq} onChange={e => setMaxMoq(+e.target.value)} style={{ width: "100%", accentColor: "var(--gold-600)" }} />
            <div className="muted" style={{ fontSize: 12, display: "flex", justifyContent: "space-between" }}><span>Any</span><span>1000+</span></div>
          </FilterGroup>
          <FilterGroup title={"Max price (USD)" + (maxPrice ? ": $" + maxPrice : "")} last>
            <input type="range" min="0" max="2000" step="50" value={maxPrice} onChange={e => setMaxPrice(+e.target.value)} style={{ width: "100%", accentColor: "var(--gold-600)" }} />
            <div className="muted" style={{ fontSize: 12, display: "flex", justifyContent: "space-between" }}><span>Any</span><span>$2000+</span></div>
          </FilterGroup>
        </aside>

        {/* Results */}
        <div>
          <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 16, flexWrap: "wrap" }}>
            <span style={{ fontWeight: 600 }}>
              {loading ? "Searching…"
                : displayTotal.toLocaleString() + " product" + (displayTotal !== 1 ? "s" : "")}
              {!loading && totalPages > 1 && (
                <span className="muted" style={{ fontWeight: 400, marginLeft: 6 }}>· page {page} of {totalPages}</span>
              )}
            </span>
            {activeFilters.map(f => <span key={f} className="badge badge-gray">{f}</span>)}
          </div>

          {/* Loading skeleton */}
          {loading && displayResults.length === 0 && (
            <div className="results-grid" style={{ display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 16 }}>
              {Array.from({ length: 6 }).map((_, i) => (
                <div key={i} className="card" style={{ height: 280, background: "var(--ink-100)", borderRadius: 14 }} />
              ))}
            </div>
          )}

          {/* Empty state */}
          {!loading && displayResults.length === 0 && (
            <div className="card" style={{ padding: 56, textAlign: "center" }}>
              <Icon name="package-search" size={40} style={{ color: "var(--ink-300)" }} />
              <h3 style={{ marginTop: 14, fontSize: 18 }}>No products match your filters</h3>
              <p className="muted" style={{ marginTop: 6 }}>Try removing a filter or posting an RFQ — suppliers will come to you.</p>
              <button className="btn btn-navy" style={{ marginTop: 18 }} onClick={() => nav("rfq")}>Post an RFQ</button>
            </div>
          )}

          {/* Product grid */}
          {displayResults.length > 0 && (
            <div className="results-grid" style={{ display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 16,
              opacity: loading ? 0.55 : 1, transition: "opacity .2s" }}>
              {displayResults.map(p => <ProductCard key={p.id} product={p} nav={nav} cur={currency} />)}
            </div>
          )}

          {/* Pagination */}
          {totalPages > 1 && (
            <Pagination page={page} totalPages={totalPages} onPage={pg => { setPage(pg); window.scrollTo({ top: 0, behavior: "smooth" }); }} />
          )}
        </div>
      </div>
    </div>
  );
}

/* ---------- Pagination ---------- */
function Pagination({ page, totalPages, onPage }) {
  const pages = [];
  const delta = 2;
  const left  = Math.max(1, page - delta);
  const right = Math.min(totalPages, page + delta);
  if (left > 1) { pages.push(1); if (left > 2) pages.push("…"); }
  for (let i = left; i <= right; i++) pages.push(i);
  if (right < totalPages) { if (right < totalPages - 1) pages.push("…"); pages.push(totalPages); }

  return (
    <div style={{ display: "flex", justifyContent: "center", gap: 6, marginTop: 36 }}>
      <button className="btn btn-ghost btn-sm" style={{ minWidth: 38, padding: "8px 0" }}
        disabled={page === 1} onClick={() => onPage(page - 1)}>
        <Icon name="chevron-left" size={16} />
      </button>
      {pages.map((p, i) =>
        p === "…" ? (
          <span key={"e" + i} style={{ padding: "8px 4px", fontSize: 13, color: "var(--ink-400)" }}>…</span>
        ) : (
          <button key={p} onClick={() => onPage(p)}
            className={p === page ? "btn btn-navy btn-sm" : "btn btn-ghost btn-sm"}
            style={{ minWidth: 38, padding: "8px 0" }}>{p}</button>
        )
      )}
      <button className="btn btn-ghost btn-sm" style={{ minWidth: 38, padding: "8px 0" }}
        disabled={page === totalPages} onClick={() => onPage(page + 1)}>
        <Icon name="chevron-right" size={16} />
      </button>
    </div>
  );
}

/* ---------- Supplier directory ---------- */
function SuppliersPage({ nav }) {
  const [country, setCountry] = useState("");
  const list = AM.SUPPLIERS.filter(s => !country || s.country === country);
  return (
    <div className="route-anim wrap" style={{ padding: "28px 24px 64px" }}>
      <Breadcrumb nav={nav} trail={[["Home", () => nav("home")], ["Suppliers"]]} />
      <div style={{ display: "flex", alignItems: "flex-end", justifyContent: "space-between", marginTop: 14, flexWrap: "wrap", gap: 14 }}>
        <div>
          <h1 style={{ fontSize: 30 }}>Verified suppliers</h1>
          <p className="muted" style={{ marginTop: 6 }}>{AM.STATS.suppliers} suppliers across all 54 countries</p>
        </div>
        <select className="select" value={country} onChange={e => setCountry(e.target.value)} style={{ width: "auto", fontWeight: 600 }}>
          <option value="">All countries</option>
          {AM.COUNTRIES.map(c => <option key={c.code} value={c.code}>{c.name}</option>)}
        </select>
      </div>
      <div className="card-grid-3" style={{ display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 16, marginTop: 24 }}>
        {list.map(s => <SupplierCard key={s.id} supplier={s} nav={nav} />)}
      </div>
    </div>
  );
}

/* ---------- Shared helpers ---------- */
function Breadcrumb({ trail }) {
  return (
    <nav style={{ display: "flex", alignItems: "center", gap: 7, fontSize: 13, color: "var(--ink-500)", flexWrap: "wrap" }}>
      {trail.map(([label, onClick], i) => (
        <React.Fragment key={i}>
          {i > 0 && <Icon name="chevron-right" size={14} style={{ color: "var(--ink-300)" }} />}
          {onClick
            ? <a onClick={onClick} style={{ cursor: "pointer", fontWeight: 500 }}
                onMouseEnter={e => e.currentTarget.style.color = "var(--navy-700)"}
                onMouseLeave={e => e.currentTarget.style.color = ""}>{label}</a>
            : <span style={{ color: "var(--ink-700)", fontWeight: 600 }}>{label}</span>}
        </React.Fragment>
      ))}
    </nav>
  );
}

function FilterGroup({ title, children, last }) {
  return (
    <div style={{ padding: "16px 0", borderBottom: last ? "none" : "1px solid var(--border)" }}>
      <div style={{ fontSize: 12.5, fontWeight: 700, color: "var(--ink-700)", marginBottom: 10 }}>{title}</div>
      {children}
    </div>
  );
}

function RadioRow({ checked, onClick, label, count }) {
  return (
    <div onClick={onClick} style={{ display: "flex", alignItems: "center", gap: 8, cursor: "pointer", padding: "5px 0", fontSize: 14, color: checked ? "var(--navy-800)" : "var(--ink-700)", fontWeight: checked ? 600 : 400 }}>
      <span style={{ width: 15, height: 15, borderRadius: "50%", border: "2px solid " + (checked ? "var(--navy-700)" : "var(--border-strong)"), display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }}>
        {checked && <span style={{ width: 7, height: 7, borderRadius: "50%", background: "var(--navy-700)" }} />}
      </span>
      <span style={{ flex: 1 }}>{label}</span>
      {count != null && <span className="muted" style={{ fontSize: 12 }}>{(count / 1000).toFixed(1)}k</span>}
    </div>
  );
}

Object.assign(window, { BrowsePage, SuppliersPage, Breadcrumb, FilterGroup, RadioRow, Pagination, AIMatch });

/* ---------- AI smart matching panel (live Claude call) ---------- */
function AIMatch({ query, nav, cur }) {
  const [state, setState] = useState({ status: "idle" });
  const reqId = useRef(0);
  useEffect(() => {
    const qq = (query || "").trim();
    if (qq.length < 3 || !window.AMAI || !AMAI.available()) { setState({ status: "idle" }); return; }
    const id = ++reqId.current;
    setState({ status: "loading" });
    const t = setTimeout(async () => {
      try {
        const data = await AMAI.smartSearch(qq);
        if (id === reqId.current) setState({ status: data.matches.length ? "done" : "empty", data });
      } catch (e) {
        if (id === reqId.current) setState({ status: "error" });
      }
    }, 750);
    return () => clearTimeout(t);
  }, [query]);

  if (state.status === "idle") return null;

  return (
    <div style={{ marginTop: 18, border: "1px solid var(--gold-300)", background: "var(--gold-50)", borderRadius: 14, padding: "16px 18px", overflow: "hidden" }}>
      <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
        <span className="ai-chip"><Icon name="sparkles" size={13} /> AI matching</span>
        <span style={{ fontSize: 14, fontWeight: 600 }}>Best matches for "{query.trim()}"</span>
        {state.status === "loading" && <Icon name="loader-circle" size={16} className="spin" style={{ color: "var(--gold-700)", marginLeft: "auto" }} />}
      </div>

      {state.status === "loading" && (
        <div className="muted" style={{ fontSize: 13.5, marginTop: 10 }}>Analyzing your request and ranking suppliers by fit, reliability and price…</div>
      )}
      {state.status === "error" && (
        <div className="muted" style={{ fontSize: 13.5, marginTop: 10, display: "flex", alignItems: "center", gap: 7 }}><Icon name="info" size={14} /> AI matching is unavailable right now — showing keyword results below.</div>
      )}
      {state.status === "empty" && (
        <div className="muted" style={{ fontSize: 13.5, marginTop: 10 }}>{state.data.summary || "No strong matches — try the filters or post an RFQ."}</div>
      )}
      {state.status === "done" && (
        <>
          <div style={{ fontSize: 13.5, color: "var(--ink-700)", marginTop: 8, lineHeight: 1.5 }}>{state.data.summary}</div>
          <div style={{ display: "flex", flexDirection: "column", gap: 8, marginTop: 12 }}>
            {state.data.matches.map((m, i) => {
              const isSup = m.kind === "supplier";
              const rec   = m.rec;
              const go    = () => isSup ? nav("store", { slug: rec.slug }) : nav("product", { slug: rec.slug });
              const sub   = isSup
                ? (AM.countryByCode[rec.country].name + " · " + rec.type)
                : (fmtPrice(rec.priceUSD, cur) + " / " + rec.unit + " · " + AM.supplierById[rec.supplier].name);
              return (
                <div key={i} onClick={go} style={{ display: "flex", alignItems: "center", gap: 12, background: "#fff", border: "1px solid var(--border)", borderRadius: 10, padding: "11px 14px", cursor: "pointer", transition: "box-shadow .15s" }}
                  onMouseEnter={e => e.currentTarget.style.boxShadow = "var(--sh-md)"} onMouseLeave={e => e.currentTarget.style.boxShadow = "none"}>
                  <span style={{ width: 44, flexShrink: 0, textAlign: "center", fontWeight: 800, fontSize: 14, color: "var(--gold-700)" }}>{m.score}<span style={{ fontSize: 9, fontWeight: 600 }}>%</span></span>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ display: "flex", alignItems: "center", gap: 7 }}>
                      <span className="badge badge-gray" style={{ fontSize: 10.5 }}><Icon name={isSup ? "building-2" : "package"} size={11} /> {isSup ? "Supplier" : "Product"}</span>
                      <span style={{ fontWeight: 700, fontSize: 14, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{rec.name}</span>
                    </div>
                    <div className="muted" style={{ fontSize: 12.5, marginTop: 3 }}>{m.reason} · {sub}</div>
                  </div>
                  <Icon name="arrow-right" size={16} style={{ color: "var(--ink-400)", flexShrink: 0 }} />
                </div>
              );
            })}
          </div>
        </>
      )}
    </div>
  );
}
