// LookPage.jsx — FLOATING look page. The indicator bubble "expands" into this
// card with a Dynamic-Island spring. The page is about ONE photo's COMPOSITION:
// big packshot rows lead (one per garment — lay-flat, name, price, size
// quick-add), with the source photo as a sticky context image (click to zoom).
// Only the clicked photo — the look's other frame is reachable from the feed,
// not from here. Below: every other look photo that features one of these
// garments, so a buyer can trace an item through the whole book.

// One garment of the composition: a BIG lay-flat packshot + its facts + sizes.
// The quick-add reuses the collection's .qa-slot cross-fade (pill ⇢ number).
function CompRow({ p, inOrder, setOrderQty, onOpenSku, cur, delay }) {
  const sizes = (p.sizes && p.sizes.length) ? p.sizes : ["ONE SIZE"];
  const qtys = (inOrder && inOrder.qtys) || {};
  const [openSize, setOpenSize] = React.useState(null);
  const editRef = React.useRef(null);
  React.useEffect(() => {
    if (openSize && editRef.current) { editRef.current.focus(); editRef.current.select(); }
  }, [openSize]);
  const setQty = (size, n) => setOrderQty(p, size, Math.max(0, n));
  const label = (s) => (s === "ONE SIZE" ? "OS" : s);
  return (
    <div className={"flp-comp-row" + (inOrder ? " is-in-order" : "")} style={{ animationDelay: delay }}>
      <button className="flp-comp-img" onClick={() => onOpenSku(p)} title={p.name}>
        {p.image ? <img src={window.sbImg(p.image, 480)} alt="" draggable={false} loading="lazy" />
                 : <span className="flp-comp-fill" style={{ background: p.bg || "var(--bg-3)" }} />}
      </button>
      <div className="flp-comp-info">
        <button className="flp-comp-name" onClick={() => onOpenSku(p)}>{(p.name || "").toLowerCase()}</button>
        <div className="flp-comp-sub">
          {p.colorway && p.colorway.name}{p.ws != null ? (
            <span className="flp-comp-price">  ·  {p.priceMode === "dtc" ? "" : "WHS "}
              {p.wsOriginal != null && <span className="price-strike">{cur}{p.wsOriginal}</span>}
              {cur}{p.ws}</span>
          ) : null}
        </div>
        <div className="flp-sizes" onMouseLeave={() => setOpenSize(null)}>
          {sizes.map((s) => {
            const active = openSize === s;
            return (
              <div key={s} className={"qa-slot" + (active ? " is-editing" : "")}>
                <button type="button" ref={window.sbHaptic}
                  className={"qa-pill" + ((qtys[s] || 0) > 0 ? " has" : "")}
                  onClick={() => p.priceMode === "dtc"
                    ? setQty(s, (qtys[s] || 0) > 0 ? 0 : 1)   /* DTC: tap size = pick it */
                    : setOpenSize(s)}>
                  {label(s)}{(qtys[s] || 0) > 1 || (p.priceMode !== "dtc" && (qtys[s] || 0) > 0) ? ` ${qtys[s]}` : ""}
                </button>
                <input type="number" min="0" className="qa-num"
                  ref={active ? editRef : null} tabIndex={active ? 0 : -1}
                  value={qtys[s] || 0}
                  onFocus={(e) => e.target.select()}
                  onChange={(e) => setQty(s, parseInt(e.target.value || "0", 10))}
                  onBlur={() => setOpenSize(null)}
                  onKeyDown={(e) => { if (e.key === "Enter" || e.key === "Escape") setOpenSize(null); }} />
              </div>
            );
          })}
        </div>
        <button className="flp-comp-view" onClick={() => onOpenSku(p)}>view piece ⟶</button>
      </div>
    </div>
  );
}

function LookPage({ look, looks, collection, info, orderItems, setOrderQty, onClose, onOpenSku, onOpenLook, onOpenConcept, frame }) {
  const ec = React.useContext(window.EditCtx);
  const [lightbox, setLightbox] = React.useState(null);   // image src or null
  const [closing, setClosing] = React.useState(false);
  const close = React.useCallback(() => { setClosing((c) => c || (setTimeout(onClose, 340), true)); }, [onClose]);

  // Open (and re-open, when browsing to another look) scrolled to the top.
  const scrollRef = React.useRef(null);
  const lastY = React.useRef(0);
  const [collapsed, setCollapsed] = React.useState(false);
  React.useEffect(() => {
    const el = scrollRef.current; if (!el) return;
    el.scrollTop = 0; setCollapsed(false); lastY.current = 0;
    setClosing(false);   // re-anchored mid-close (back/forward) → never a stuck invisible scrim
    const r = requestAnimationFrame(() => { el.scrollTop = 0; });
    return () => cancelAnimationFrame(r);
  }, [look.id, frame]);
  const onScroll = (e) => {
    const y = e.currentTarget.scrollTop, dy = y - lastY.current;
    if (y < 14) setCollapsed(false);
    else if (dy > 5) setCollapsed(true);
    else if (dy < -5) setCollapsed(false);
    lastY.current = y;
  };

  const realImages = (look.images || []).filter(Boolean);
  const i = Math.max(0, Math.min(frame || 0, Math.max(0, realImages.length - 1)));
  const hero = realImages[i];
  const m = (look.imageMeta || [])[i] || {};
  const productIds = m.skuIds || [];
  const skus = productIds.map((id) => collection.find((p) => p.id === id)).filter(Boolean);
  const cur = info && info.currency ? info.currency : "";

  // "in other looks" — only photos that actually feature one of THESE garments.
  const gallery = [];
  const seen = new Set();
  if (productIds.length) {
    for (const L of (looks || [])) {
      const imgs = (L.images || []).filter(Boolean);
      (L.imageMeta || []).forEach((mm, j) => {
        const ids = (mm && mm.skuIds) || [];
        if (!ids.some((id) => productIds.includes(id))) return;   // must share a garment
        if (L.id === look.id && j === i) return;                  // skip the photo we're on
        const src = imgs[j];
        if (src && !seen.has(src)) { seen.add(src); gallery.push({ src, lookId: L.id, frame: j, n: L.n }); }
      });
    }
  }

  React.useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") { if (lightbox) setLightbox(null); else close(); } };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [lightbox, close]);

  return (
    <div className={"flp-overlay" + (closing ? " is-closing" : "")} onClick={close} role="dialog" aria-modal="true">
      <div className="flp-card" onClick={(e) => e.stopPropagation()}>
        <div className={"flp-head" + (collapsed ? " is-collapsed" : "")}>
          <span className="flp-title"><b>LOOK · {look.n}</b>{look.name && <span className="flp-title-name">{" / " + look.name.toUpperCase()}</span>}</span>
          <span className="flp-head-meta">{skus.length > 0 ? String(skus.length).padStart(2, "0") + (skus.length === 1 ? " PIECE" : " PIECES") : ""}</span>
        </div>

        <div className="flp-scroll" ref={scrollRef} onScroll={onScroll}>
          <div className="flp-comp">
            {/* the composition — the garments that build this look, packshots first */}
            <div className="flp-comp-main">
              <div className="flp-side-label">the composition</div>
              {skus.length > 0 ? (
                skus.map((p, k) => (
                  <CompRow key={p.id} p={p} inOrder={orderItems[p.id]} setOrderQty={setOrderQty}
                    onOpenSku={onOpenSku} cur={cur} delay={(0.14 + k * 0.08).toFixed(2) + "s"} />
                ))
              ) : (
                <div className="flp-items-empty">no garments tagged on this photo yet.</div>
              )}
            </div>

            {/* small context column — the photo this page came from */}
            <aside className="flp-context">
              <div className="flp-side-label">worn in</div>
              <button className="flp-ctx-photo" onClick={() => hero && setLightbox(hero)} title="zoom">
                {hero ? <img src={hero} alt="" draggable={false}
                          srcSet={window.sbSrcSet(hero)} sizes="(max-width: 600px) 92vw, 320px" />
                      : <span className="flp-hero-none">◯</span>}
              </button>
              {look.body ? <p className="flp-ctx-body">{look.body}</p> : null}
            </aside>
          </div>

          {gallery.length > 0 && (
            <div className="flp-more">
              <div className="flp-sec-h">these pieces in other looks <span className="flp-sec-count">{String(gallery.length).padStart(2, "0")}</span></div>
              <div className="flp-gallery">
                {gallery.map((g, k) => (
                  <button key={g.src + k} className="flp-gtile"
                    onClick={() => (onOpenLook ? onOpenLook(g.lookId, g.frame) : setLightbox(g.src))} title="open look">
                    <img src={g.src} alt="" loading="lazy"
                      srcSet={window.sbSrcSet(g.src)} sizes="(max-width: 600px) 46vw, 24vw" />
                    {g.n != null && <span className="flp-gtile-chip">LOOK · {g.n}</span>}
                  </button>
                ))}
              </div>
            </div>
          )}
        </div>
      </div>

      <button className="flp-closepill" onClick={(e) => { e.stopPropagation(); close(); }} title="close">✕ close</button>

      {lightbox && (
        <div className="flp-lightbox" onClick={(e) => { e.stopPropagation(); setLightbox(null); }}>
          <button className="flp-lightbox-close" onClick={() => setLightbox(null)}>×</button>
          <img src={window.sbImg(lightbox, 2000)} alt="" onClick={(e) => e.stopPropagation()} />
        </div>
      )}
    </div>
  );
}

window.LookPage = LookPage;
