// Pull-City — page sections (sealed-only)

const { useState } = React;

// Toast leggero per feedback "link copiato".
function pcToast(msg) {
  let el = document.getElementById("pc-toast");
  if (!el) {
    el = document.createElement("div");
    el.id = "pc-toast";
    el.style.cssText = "position:fixed;left:50%;bottom:32px;transform:translateX(-50%);z-index:9999;background:var(--surface,#15121f);color:var(--ink,#fff);border:1px solid var(--line-2,rgba(255,255,255,.18));padding:11px 18px;border-radius:999px;font-size:13px;box-shadow:0 12px 30px rgba(0,0,0,.5);opacity:0;transition:opacity .2s,transform .2s;pointer-events:none";
    document.body.appendChild(el);
  }
  el.textContent = msg;
  requestAnimationFrame(() => { el.style.opacity = "1"; el.style.transform = "translateX(-50%) translateY(-4px)"; });
  clearTimeout(el._t);
  el._t = setTimeout(() => { el.style.opacity = "0"; el.style.transform = "translateX(-50%)"; }, 1800);
}

// Link condivisibile per ogni prodotto: <origin>/?p=<id>.
function pcShareProduct(p) {
  const url = location.origin + "/p/" + encodeURIComponent(p.id);
  if (navigator.share) { navigator.share({ title: "Pull-City · " + p.name, url }).catch(() => {}); return; }
  if (navigator.clipboard) { navigator.clipboard.writeText(url).then(() => pcToast("Link copiato")).catch(() => window.prompt("Copia il link:", url)); }
  else { window.prompt("Copia il link del prodotto:", url); }
}

function Marquee() {
  const items = [
    "Sealed", "Booster Box", "Elite Trainer Box", "Pre-order Aperti",
    "Spedizione Corazzata", "Originali Garantiti", "Display Sigillato",
    "Drop Settimanali", "Mai aperti", "Vault Edition"
  ];
  const row = items.concat(items).concat(items);
  return (
    <div className="marquee">
      <div className="track">
        {row.map((t, i) => (
          <span key={i} className="item">
            <span className="star">✦</span><em>{t}</em>
          </span>
        ))}
      </div>
    </div>
  );
}

function CountUp({ to, suffix = "", duration = 1400, decimals = 0 }) {
  const [val, setVal] = React.useState(0);
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    let raf = 0, started = false, t0 = 0;
    function step(t) {
      if (!t0) t0 = t;
      const p = Math.min(1, (t - t0) / duration);
      const ease = 1 - Math.pow(1 - p, 3);
      setVal(to * ease);
      if (p < 1) raf = requestAnimationFrame(step);
    }
    const io = new IntersectionObserver((entries) => {
      entries.forEach(en => {
        if (en.isIntersecting && !started) { started = true; raf = requestAnimationFrame(step); io.disconnect(); }
      });
    }, { threshold: 0.5 });
    io.observe(el);
    return () => { io.disconnect(); if (raf) cancelAnimationFrame(raf); };
  }, [to, duration]);
  const out = decimals > 0 ? val.toFixed(decimals) : Math.round(val).toLocaleString("it-IT");
  return <span ref={ref}>{out}{suffix}</span>;
}

function BrandStatement() {
  return (
    <section className="section">
      <div className="wrap manifesto">
        <div className="reveal">
          <span className="eyebrow"><span className="dot" />Il Vault</span>
          <p className="big" style={{ marginTop: 22 }}>
            Solo prodotti <em>sigillati.</em><br />Solo i drop che valgono davvero.
          </p>
        </div>
        <div className="reveal">
          <div className="small">
            <p>Pull-City TCG è un archivio di booster box, display, elite trainer e starter deck — sigillati di fabbrica, conservati in ambiente climatizzato, mai manomessi.</p>
            <p>Lavoriamo con Yu-Gi-Oh!, Pokémon, One Piece, Dragon Ball Fusion World, Union Arena, CCG anime (Bleach, Naruto) e magazine giapponesi. Selezione curata: il prodotto che trovi qui è quello che cerchi davvero, e arriva esattamente come è uscito di fabbrica.</p>
          </div>
          <div className="ledger">
            <div><div className="k"><CountUp to={38} /></div><div className="l">Set in catalogo</div></div>
            <div><div className="k"><CountUp to={12} /></div><div className="l">Pre-order aperti</div></div>
            <div><div className="k"><CountUp to={48} suffix="h" /></div><div className="l">Consegna media</div></div>
          </div>
        </div>
      </div>
    </section>
  );
}

// Single sealed product card with cursor-tracking tilt + spotlight
function SealedCard({ product, onAdd, onQuick }) {
  const isPre = product.status === "preorder";
  const soldOut = !!product.sold_out || product.stock === 0;
  const ref = React.useRef(null);
  const boxRef = React.useRef(null);
  function onMove(e) {
    const el = ref.current; if (!el) return;
    const r = el.getBoundingClientRect();
    const x = (e.clientX - r.left) / r.width;
    const y = (e.clientY - r.top) / r.height;
    el.style.setProperty("--mx", (x * 100) + "%");
    el.style.setProperty("--my", (y * 100) + "%");
    if (boxRef.current) {
      const rx = (y - 0.5) * -8;
      const ry = (x - 0.5) * 10;
      boxRef.current.style.transform = `translateY(-8px) rotateX(${rx}deg) rotateY(${ry}deg)`;
    }
  }
  function onLeave() {
    if (boxRef.current) boxRef.current.style.transform = "";
  }
  return (
    <div className={"sealed-card " + (product.variant || "")} ref={ref}
         onMouseMove={onMove} onMouseLeave={onLeave}
         onClick={() => onQuick && onQuick(product)}>
      <div className="corner">
        <span className={"pill-status " + (soldOut ? "sold" : isPre ? "pre" : "")}>
          <span className="dot" />
          {soldOut ? "Esaurito" : isPre ? "Pre-order" : "Disponibile"}
        </span>
        {!isPre && !soldOut && product.stock != null && (
          <span className="pill-stock">{product.stock} pz</span>
        )}
      </div>
      <div className="imgwrap">
        <div className="box-tilt" ref={boxRef}>
          <div className="product-photo">
            {product.image ? (
              <img src={product.image} alt={[(product.franchise || product.label || "").trim(), product.name, "— sigillato originale"].filter(Boolean).join(" ")} loading="lazy" decoding="async"
                   onError={(e) => { e.currentTarget.style.display = "none"; const ph = e.currentTarget.parentElement.querySelector('.photo-placeholder'); if (ph) ph.style.display = "flex"; }} />
            ) : null}
            <div className="photo-placeholder" style={{ display: product.image ? "none" : "flex" }}>
              <div className="ph-glyph">{product.glyph || "✦"}</div>
              <div className="ph-franchise">{product.franchise || product.label}</div>
              <div className="ph-name">{product.name}</div>
            </div>
          </div>
        </div>
      </div>
      <div className="info">
        <div className="row1">
          <span className="nm">{product.name}</span>
          <span className="pr">€ {typeof product.price === "number" ? product.price.toLocaleString("it-IT") : product.price}</span>
        </div>
        <span className="sub">{product.sub}</span>
        {isPre && product.release && (
          <span className="release">In uscita {product.release}</span>
        )}
        <div className="cta-row">
          <button className={"btn-sm " + (isPre ? "gold" : "solid")} disabled={soldOut} onClick={(e) => { e.stopPropagation(); if (soldOut) return; onAdd && onAdd(product); }}>
            {soldOut ? "Esaurito" : isPre ? "Prenota" : "Aggiungi"}
          </button>
          <button className="btn-sm ghost" onClick={(e) => { e.stopPropagation(); onQuick && onQuick(product); }} aria-label="Dettagli">Dettagli</button>
          <button className="btn-sm ghost" onClick={(e) => { e.stopPropagation(); pcShareProduct(product); }} aria-label="Condividi" title="Condividi il link del prodotto">↗</button>
        </div>
      </div>
    </div>
  );
}

// One universe section with available / preorder tabs
const DEFAULT_FORMATS = [{ value: "tcg", label: "TCG", sub: "inglese" }, { value: "ocg", label: "OCG", sub: "giapponese" }];

function UniverseSection({ idAttr, num, name, tag, intro, products, onAdd, onQuick, logo, logos, chips, formats = DEFAULT_FORMATS }) {
  const [fmt, setFmt] = useState(formats[0].value);
  const [tab, setTab] = useState("available");
  const byFmt = products.filter(p => String(p.format || "tcg").split(/[,\s]+/).filter(Boolean).includes(fmt));
  const available = byFmt.filter(p => p.status === "available");
  const preorder = byFmt.filter(p => p.status === "preorder");
  const shown = tab === "available" ? available : preorder;

  return (
    <section className="section univ-section" id={idAttr}>
      <div className="wrap">
        <div className="univ-head reveal">
          <div className="titles">
            <span className="eyebrow"><span className="dot" />{tag}</span>
            <h2 className="electric-title">{name}</h2>
          </div>
          <div className="universe-mark">
            <div className="num">{num}</div>
            <div className={"ico franchise-ico" + ((logos && logos.length) ? " franchise-ico--multi" : "")}>
              {logos && logos.length
                ? logos.map((src, i) => <img key={i} src={src} alt={(src.split("/").pop().replace(/\.[a-z]+$/i, "").replace(/^\w/, (c) => c.toUpperCase())) + " — carte sigillate Pull-City"} onError={(e)=>{ e.currentTarget.style.display="none"; }} />)
                : logo
                ? <img src={logo} alt={name} onError={(e)=>{ e.currentTarget.style.display="none"; const fb = e.currentTarget.parentElement.querySelector('.franchise-fallback'); if (fb) fb.style.display="grid"; }} />
                : null}
              {(chips || []).map((c, i) => <span key={i} className="franchise-chip">{c}</span>)}
              <span className="franchise-fallback" style={{ display: (logo || (logos && logos.length)) ? "none" : "grid" }}>{(name || "").charAt(0)}</span>
            </div>
          </div>
        </div>

        {formats.length > 1 && (
          <div className="univ-fmt reveal" role="tablist" aria-label="Formato">
            {formats.map((ff) => (
              <button key={ff.value} className={"fmt-tab" + (fmt === ff.value ? " active" : "")} onClick={() => setFmt(ff.value)} role="tab">
                <span className="fmt-mark">{ff.label}</span><span className="fmt-sub">{ff.sub}</span>
              </button>
            ))}
          </div>
        )}

        <div className="univ-tabs reveal">
          <div className="tabset" role="tablist">
            <button className={"tab" + (tab === "available" ? " active" : "")} onClick={() => setTab("available")} role="tab">
              Disponibili <span className="count">{available.length}</span>
            </button>
            <button className={"tab" + (tab === "preorder" ? " active" : "")} onClick={() => setTab("preorder")} role="tab">
              Pre-order <span className="count">{preorder.length}</span>
            </button>
          </div>
          <div className="meta">{shown.length} prodotti</div>
        </div>

        <div className="univ-grid" key={fmt + "/" + tab}>
          {shown.map((p, i) => (
            <div key={p.id} className="univ-grid-item" style={{ "--i": i, animation: "univItemIn .5s " + (i * 0.06) + "s both cubic-bezier(.2,.7,.2,1)" }}>
              <SealedCard product={p} onAdd={onAdd} onQuick={onQuick} />
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

// Config franchise (loghi/formati). L'ordine di visualizzazione è automatico:
// prima le sezioni che hanno prodotti, poi le vuote (ordine canonico preservato).
const UNIVERSE_CONFIG = [
  { key: "ygo",  logo: "media/logos/yugioh.png" },
  { key: "pkm",  logo: "media/logos/pokemon.png" },
  { key: "op",   logo: "media/logos/onepiece.png" },
  { key: "dbfw", logo: "media/logos/dragonball.png" },
  { key: "ua",   logo: "media/logos/unionarena.png" },
  { key: "ccg",  logos: ["media/logos/naruto.png", "media/logos/bleach.png", "media/logos/firelegends.svg"], formats: [{ value: "eng", label: "ENG", sub: "inglese" }, { value: "cn", label: "CN", sub: "cinese" }] },
  { key: "mag",  logo: "media/logos/jump.png", formats: [{ value: "ocg", label: "OCG", sub: "giapponese" }] },
];

function Universes({ onAdd, onQuick }) {
  const d = window.PC_DATA || {};
  const items = UNIVERSE_CONFIG
    .filter((c) => d[c.key])
    .map((c, i) => ({ ...c, data: d[c.key], count: (d[c.key].products || []).length, order: i }));
  // Sort stabile: non-vuote prima, vuote dopo; a parità mantiene l'ordine canonico.
  const sorted = items.slice().sort((a, b) => {
    const ea = a.count > 0 ? 0 : 1, eb = b.count > 0 ? 0 : 1;
    return ea !== eb ? ea - eb : a.order - b.order;
  });
  return (
    <>
      {sorted.map((c, idx) => (
        <UniverseSection
          key={c.key}
          idAttr={c.key}
          num={"Universo " + String(idx + 1).padStart(2, "0")}
          {...c.data}
          logo={c.logo}
          logos={c.logos}
          formats={c.formats}
          onAdd={onAdd}
          onQuick={onQuick}
        />
      ))}
    </>
  );
}

function Trust() {
  const items = [
    { n: "01", l: "Sigillati di fabbrica", d: "Ogni booster, display e starter è sigillato originale. Nessuna apertura, nessuna manomissione." },
    { n: "02", l: "Conservati in clima",   d: "Vault a temperatura e umidità controllate. Le buste non subiscono stress prima della consegna." },
    { n: "03", l: "Spedizione corazzata",  d: "Box rigido, riempimento in schiuma e tracking firmato. Arrivano come sono entrati nel vault." },
    { n: "04", l: "Pre-order garantiti",   d: "Prezzo bloccato al momento dell'ordine. Se il prodotto non arriva, rimborso integrale immediato." }
  ];
  return (
    <section className="section" id="trust">
      <div className="wrap">
        <div className="section-head reveal">
          <div className="titles">
            <span className="eyebrow"><span className="dot" />Vault Standard</span>
            <h2>Quattro passi tra te e <em>il sigillo.</em></h2>
            <p>Il valore di un sigillato si misura in fiducia. Ecco come la costruiamo.</p>
          </div>
        </div>
        <div className="trust">
          {items.map((t, i) => (
            <div key={i} className="t reveal">
              <div className="n">{t.n}</div>
              <div className="l">{t.l}</div>
              <div className="d">{t.d}</div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

function VaultLive({ onCta, onSubscribe, tiktok, twitch }) {
  return (
    <section className="endcta vault-live" id="live">
      <div className="wrap reveal">
        <span className="eyebrow"><span className="dot" />Vault Access · Live</span>
        <h2 style={{ marginTop: 24 }}>Entra nel <em>Vault.</em></h2>
        <p>Drop settimanali, priorità sui pre-order e prezzi bloccati per i soci. E sbustiamo le box insieme a te — in diretta su TikTok e Twitch.</p>
        <div className="ctas">
          <button className="btn btn-gold" onClick={() => onCta && onCta("ygo")}>
            Apri il Vault
            <svg className="arr" width="14" height="14" viewBox="0 0 24 24" fill="none"><path d="M5 12h14M13 6l6 6-6 6" stroke="currentColor" strokeWidth="1.6"/></svg>
          </button>
          <button className="btn btn-ghost" onClick={() => onSubscribe && onSubscribe()}>Iscriviti ai drop</button>
        </div>
        <div className="vault-live-row">
          <span className="live-badge"><span className="live-dot" />Sbustiamo in diretta</span>
          <div className="live-ctas">
            <a className="live-btn tiktok" href={tiktok} target="_blank" rel="noopener">
              <svg width="20" height="20" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M16.6 5.82a4.28 4.28 0 0 1-1.06-2.82h-3.2v12.06a2.6 2.6 0 1 1-2.04-2.54V9.27a5.8 5.8 0 1 0 5.24 5.77V9.18a7.36 7.36 0 0 0 4.32 1.38V7.36a4.28 4.28 0 0 1-3.26-1.54z"/></svg>
              Live su TikTok
            </a>
            <span className="live-btn twitch soon" aria-disabled="true" title="Live Twitch in arrivo">
              <svg width="18" height="18" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M4 2 3 6v14h5v3h3l3-3h4l5-5V2H4zm17 11-3 3h-4l-3 3v-3H7V4h14v9zM16 7h-2v5h2V7zm-5 0H9v5h2V7z"/></svg>
              Twitch · Coming soon
            </span>
          </div>
        </div>
      </div>
    </section>
  );
}

function Footer() {
  return (
    <footer className="footer">
      <div className="wrap">
        <div className="footer-grid">
          <div className="footer-brand">
            <img src="media/logo-full.png" alt="Pull-City TCG — carte sigillate Treviso e Venezia" className="footer-logo" />
            <p className="footer-claim">Carte TCG sigillate originali — booster box, display e pre-order. Treviso e Venezia, spedizione in tutta Italia.</p>
          </div>
          <nav className="footer-col" aria-label="Catalogo">
            <h4>Catalogo</h4>
            <a href="#ygo">Yu-Gi-Oh!</a>
            <a href="#pkm">Pokémon</a>
            <a href="#op">One Piece</a>
            <a href="#dbfw">Dragon Ball</a>
            <a href="#ua">Union Arena</a>
            <a href="#ccg">CCG</a>
            <a href="#mag">Magazine</a>
          </nav>
          <nav className="footer-col" aria-label="Contatti">
            <h4>Contatti</h4>
            <a href="mailto:info@pullcitytcg.it">info@pullcitytcg.it</a>
            <a href="https://chat.whatsapp.com/" target="_blank" rel="noopener">Gruppo WhatsApp</a>
            <a href="https://www.tiktok.com/@pullcitytcg" target="_blank" rel="noopener">TikTok</a>
            <span className="footer-soon">Twitch · Coming soon</span>
          </nav>
          <nav className="footer-col" aria-label="Informazioni">
            <h4>Info</h4>
            <a href="terms.html">Termini &amp; Condizioni</a>
            <a href="privacy.html">Privacy</a>
            <a href="cookies.html">Cookie</a>
          </nav>
        </div>
        <div className="footer-bottom">
          <span className="fb-left">© 2026 Pull-City TCG — Treviso · Venezia · P.IVA 03821740368</span>
          <span className="fb-right">Sealed garantito · Spedizione in tutta Italia</span>
        </div>
      </div>
    </footer>
  );
}

Object.assign(window, { Marquee, BrandStatement, Universes, UniverseSection, SealedCard, Trust, VaultLive, Footer });
