/* ============================================================
   3DAX — Catalog grid
   ============================================================ */
function ProductCard({ p, onOpen, index }){
  const [hover, setHover] = useState(false);
  const [repoFailed, setRepoFailed] = useState(false);
  // prioridad: foto del listing (data URL en BD) → preview de repo → placeholder
  const repoPreview = (p.model && p.id) ? ("assets/previews/" + p.id + ".png") : null;
  const listImg = (p.images && p.images.length > 0) ? p.images[0] : null;
  const main = listImg || (repoPreview && !repoFailed ? repoPreview : null);
  const hasImg = !!main;
  const alt = (p.images && p.images[1]) ? p.images[1] : main;

  const openFicha = () => {
    try {
      sessionStorage.setItem("3dax_view", JSON.stringify({
        id:p.id, char:p.char, name:p.name, price:p.price, franchise:p.franchise,
        images:p.images, blurb:p.blurb, colorways:p.colorways, specs:p.specs, model:p.model || null,
      }));
    } catch(e){}
    window.location.href = "experiencia-3d.html?id=" + encodeURIComponent(p.id);
  };

  return (
    <Reveal delay={(index % 3) * 90} className="card"
      style={{ cursor:"pointer" }}>
      <div className="card__inner"
           onMouseEnter={() => setHover(true)}
           onMouseLeave={() => setHover(false)}
           onClick={openFicha}>
        <div className="card__media" style={{ background:`radial-gradient(70% 65% at 50% 42%, ${(p.colorways&&p.colorways[0]||{from:'#cda14e'}).from}, ${(p.colorways&&p.colorways[0]||{from:'#cda14e'}).from}66 38%, transparent 72%)` }}>
          {p.featured && <span className="card__badge card__badge--feat">★ Destacado</span>}
          {p.placeholder && <span className="card__badge">Próximamente</span>}
          {hasImg ? (
            <div className="card__imgwrap">
              <img className="card__img" src={main} alt={p.seoAlt || p.name}
                   style={{ opacity: hover && alt!==main ? 0 : 1 }}
                   onError={() => { if(main===repoPreview) setRepoFailed(true); }} />
              {alt!==main && <img className="card__img card__img--alt" src={alt} alt=""
                   style={{ opacity: hover ? 1 : 0 }} />}
            </div>
          ) : (
            <ProductPlaceholder label="render en camino"
              from={p.colorways[0].from} to={p.colorways[0].to} />
          )}
          <div className="card__hoverbar">
            <span>{p.placeholder ? "Vista previa 3D" : "Ver en 3D"}</span>
            <span className="arr">→</span>
          </div>
        </div>

        <div className="card__body">
          <div className="card__char">{p.char}</div>
          <div className="card__row">
            <h3 className="card__name">{p.name}</h3>
            <div className="card__price">{eur(p.price)}</div>
          </div>
          <div className="card__meta">
            <Stars value={p.rating} size={12} />
            <span className="card__reviews">{p.rating} · {p.reviews} reseñas</span>
          </div>
          <div className="card__ways">
            {p.colorways.map((c, i) => (
              <span key={i} className="way" title={c.name}
                    style={{ background:`linear-gradient(135deg, ${c.from}, ${c.to})` }} />
            ))}
            <span className="card__waylbl">{p.colorways.length} acabados</span>
          </div>
        </div>
      </div>
    </Reveal>
  );
}

function Catalog({ products, onOpen }){
  const { FRANCHISES } = window.DATA;
  const [filter, setFilter] = useState("Todas");

  // categories present in the live catalog, ordered by the canonical FRANCHISES list
  const order = FRANCHISES.map((f) => f.name);
  const present = [...new Set(products.map((p) => p.franchise || "Otros"))]
    .sort((a, b) => (order.indexOf(a) === -1 ? 99 : order.indexOf(a)) - (order.indexOf(b) === -1 ? 99 : order.indexOf(b)));
  const cats = ["Todas", ...present];

  // deep-link: index.html#col=One%20Piece%20TCG
  useEffect(() => {
    const read = () => {
      const m = (window.location.hash || "").match(/col=([^&]+)/);
      if (m) {
        const name = decodeURIComponent(m[1].replace(/\+/g, " "));
        const hit = present.find((c) => c.toLowerCase() === name.toLowerCase());
        if (hit) setFilter(hit);
      }
    };
    read();
    window.addEventListener("hashchange", read);
    return () => window.removeEventListener("hashchange", read);
  }, [products.length]);

  const shown = filter === "Todas" ? products : products.filter((p) => (p.franchise || "Otros") === filter);
  const meta = FRANCHISES.find((f) => f.name === filter);
  const goCat = (name) => {
    setFilter(name);
    const el = document.getElementById("coleccion");
    if (el) window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 70, behavior: "smooth" });
  };

  return (
    <section className="catalog section grain" id="coleccion" data-screen-label="Colección">
      <div className="wrap">
        <div className="catalog__head">
          <Reveal>
            <div className="eyebrow">{filter === "Todas" ? "La colección" : "Colección"}</div>
            <h2 className="display catalog__title">
              {filter === "Todas" ? "Elige tu tripulación" : filter}
            </h2>
          </Reveal>
          <Reveal delay={120}>
            <p className="lead catalog__sub">
              {filter === "Todas"
                ? "Explora por universo. Nuevos diseños cada mes — y más de 50 esperando en el taller."
                : (meta ? meta.note : "Deckbox custom esculpidas a mano para este universo.")}
            </p>
          </Reveal>
        </div>

        {/* collection filter tabs */}
        <div className="catfilter" role="tablist">
          {cats.map((c) => {
            const count = c === "Todas" ? products.length : products.filter((p) => (p.franchise || "Otros") === c).length;
            return (
              <button key={c} role="tab" aria-selected={filter === c}
                      className={"catfilter__tab" + (filter === c ? " on" : "")}
                      onClick={() => setFilter(c)}>
                {c} <span className="catfilter__n">{count}</span>
              </button>
            );
          })}
        </div>

        {shown.length === 0 ? (
          <div className="catalog__empty">
            <div className="catalog__empty-ic">◳</div>
            <h3 className="display">Aún no hay diseños de {filter} publicados</h3>
            <p>Estamos esculpiendo nuevos modelos para este universo. ¿Quieres uno concreto? Te lo hacemos a medida.</p>
            <a className="btn btn-primary" href="custom-deckbox.html">Pedir a medida →</a>
          </div>
        ) : (
          <div className="catalog__grid">
            {shown.map((p, i) => (
              <ProductCard key={p.id} p={p} index={i} onOpen={onOpen} />
            ))}
          </div>
        )}

        <Reveal className="franchises">
          <div className="franchises__head">
            <h3>Explora por universo</h3>
            <p>Más de 50 diseños esculpidos en 6 universos. ¿No ves tu personaje? Pídelo a medida.</p>
          </div>
          <div className="franchises__grid">
            {FRANCHISES.map((f, i) => {
              const live = products.filter((p) => (p.franchise || "Otros") === f.name).length;
              return (
                <button className="fcard" key={i} onClick={() => goCat(f.name)}>
                  <div className="fcard__top">
                    <span className="fcard__name">{f.name}</span>
                    <span className="fcard__count">{live > 0 ? live + " en tienda" : f.count + " diseños"}</span>
                  </div>
                  <span className="fcard__note">{f.note}</span>
                  <span className="fcard__go">Ver colección →</span>
                </button>
              );
            })}
          </div>
        </Reveal>
      </div>
    </section>
  );
}
window.Catalog = Catalog;
