// ── HomeDeck: horizontal scroll-scrub deck (new homepage experience) ──
// Desktop: wheel/scroll scrubs the active panel's video frame-by-frame; once a
// panel is fully scrubbed, the next slides in elegantly. Mobile: no video — a
// horizontal swipe-snap strip of first-frame posters (fast, light). Section
// titles are live links the whole time. Flag-gated: ?deck=on to preview,
// window.DECK_ON to force; default OFF so it can't disturb the live home until
// flipped on in app.jsx.
//
// Watermark crop: every media element is overscanned (scale ~1.1, overflow
// hidden) so the source clips' bottom-right Gemini mark is pushed off-frame.

const DECK_OVERSCAN = 1.0;            // footage at native scale (vignette hides the de-logo corner)
const SCRUB_SENSITIVITY = 1200;       // wheel px to scrub one full panel (higher = slower, smoother)
const BESPOKE_CAP_S = 5;              // bespoke panel scrubs only 0–5s

function deckPanels(goTo) {
  return [
    { key: 'intro',   src: 'assets/deck/intro.mp4',   poster: 'assets/deck/intro.jpg',   mobilePoster: 'assets/deck/intro-m.jpg',   kind: 'wordmark' },
    { key: 'men',     src: 'assets/deck/men.mp4',     poster: 'assets/deck/men.jpg',     mobilePoster: 'assets/deck/men-m.jpg',     title: 'Men',     go: () => goTo('collection', { gender: 'Men' }) },
    { key: 'women',   src: 'assets/deck/women.mp4',   poster: 'assets/deck/women.jpg',   mobilePoster: 'assets/deck/women-m.jpg',   title: 'Women',   go: () => goTo('collection', { gender: 'Women' }) },
    { key: 'luxury',  src: 'assets/deck/luxury.mp4',  poster: 'assets/deck/luxury.jpg',  mobilePoster: 'assets/deck/luxury-m.jpg',  title: 'Luxury',  go: () => goTo('collection', { season: 'Luxury' }) },
    { key: 'bespoke', src: 'assets/deck/bespoke.mp4', poster: 'assets/deck/bespoke.jpg', mobilePoster: 'assets/deck/bespoke-m.jpg', title: 'Bespoke', cap: BESPOKE_CAP_S, go: () => window.openBespoke && window.openBespoke() },
    { key: 'journal', src: 'assets/deck/journal.mp4', poster: 'assets/deck/journal.jpg', mobilePoster: 'assets/deck/journal-m.jpg', mobilePos: '74% center', title: 'Journal', journal: true, go: () => goTo('journal') },
    { key: 'footer',  footer: true },
  ];
}

// Title overlay — clickable section label, top-left (intro = centered wordmark).
function DeckTitle({ panel, onAdvance }) {
  const ink = '#F4F1EC', shadow = '0 2px 30px rgba(0,0,0,.55)';
  if (panel.kind === 'wordmark') {
    return (
      <>
        <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column',
          alignItems: 'center', justifyContent: 'center', pointerEvents: 'none', textShadow: shadow }}>
          <div className="wordmark deck-jt" style={{ lineHeight: .9, color: ink, letterSpacing: '-.01em' }}>JT</div>
          <div className="deck-atelier" style={{ letterSpacing: '.28em', textTransform: 'uppercase',
            fontFamily: 'var(--font-display)', color: 'var(--crimson,#c0322b)', marginTop: '.1em' }}>ATELIER</div>
        </div>
        {/* balancing corner bars on the intro panel (no category) */}
        <div className="deck-bar deck-bar-tl deck-bar-intro"><span className="deck-bar-label">EST. 2026</span></div>
        <button onClick={onAdvance} aria-label="Enter" className="deck-bar deck-bar-br deck-bar-enter"><span className="deck-bar-title">Enter →</span></button>
      </>
    );
  }
  if (!panel.title) return null;
  // Two angled label-bars emerging from opposite corners: a black bar top-left
  // (light text) and a colour-flipped white bar bottom-right (dark text) — the
  // bottom bar also covers the de-logo'd corner. Both link to the category.
  return (
    <>
      {/* top-left black bar */}
      <button onClick={panel.go} aria-label={panel.title} className="deck-bar deck-bar-tl">
        <span className="deck-bar-title">{panel.title}</span>
        <span className="deck-bar-view">VIEW →</span>
      </button>
      {/* bottom-right flipped white bar (covers watermark corner) */}
      <button onClick={panel.go} aria-label={panel.title} className="deck-bar deck-bar-br">
        <span className="deck-bar-title">{panel.title}</span>
        <span className="deck-bar-view">VIEW →</span>
      </button>
    </>
  );
}

// Journal cards — bottom-right, flip in as the journal panel scrubs (t 0→1).
function DeckJournalCards({ t, goTo }) {
  const entries = (window.JOURNAL_ENTRIES || []).slice(0, 5);
  if (entries.length === 0) return null;
  const n = entries.length;
  return (
    <div style={{ position: 'absolute', right: 'clamp(20px,4vw,70px)', bottom: 'clamp(24px,5vh,70px)',
      width: 'clamp(220px,26vw,330px)', height: 'clamp(300px,40vh,460px)', zIndex: 5, pointerEvents: 'auto' }}>
      {entries.map((e, i) => {
        // each card flips over its own slice of the scrub
        const slice = 1 / n;
        const local = Math.max(0, Math.min(1, (t - i * slice) / slice));
        const flipped = local;                       // 0 unflipped → 1 flipped/gone
        const settle = i < Math.floor(t * n) ? 1 : 0;
        return (
          <button key={e.id} onClick={() => goTo('journal')}
            style={{ position: 'absolute', inset: 0, border: 'none', padding: 0, cursor: 'pointer',
              transformStyle: 'preserve-3d', transformOrigin: 'right center',
              transform: `translateY(${-i * 6}px) rotateY(${-flipped * 100}deg) scale(${1 - i * 0.02})`,
              opacity: flipped > 0.9 ? Math.max(0, 1 - (flipped - 0.9) / 0.1) : 1,
              zIndex: 50 - i, transition: 'box-shadow .2s',
              boxShadow: '0 24px 60px rgba(0,0,0,.4)', background: '#F4F1EC',
              backfaceVisibility: 'hidden' }}>
            <div style={{ position: 'absolute', inset: 0, overflow: 'hidden', background: '#EFE9DD' }}>
              <img src={e.image} alt="" onError={ev => { if (e.fallback) ev.currentTarget.src = e.fallback; }}
                style={{ width: '100%', height: '64%', objectFit: 'cover', objectPosition: e.imgPos || 'center', display: 'block' }} />
              <div style={{ padding: '14px 16px', textAlign: 'left' }}>
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 9, letterSpacing: '.16em',
                  textTransform: 'uppercase', color: 'rgba(26,26,26,.5)', marginBottom: 6 }}>{e.category} · {e.date}</div>
                <div style={{ fontFamily: 'var(--font-display)', fontSize: 18, lineHeight: 1.1, color: '#1A1A1A' }}>{e.title}</div>
              </div>
            </div>
          </button>
        );
      })}
    </div>
  );
}

function HomeDeck({ goTo, FooterCmp, openNewsletter }) {
  const panels = React.useMemo(() => deckPanels(goTo), [goTo]);
  const N = panels.length;
  const mobile = window.useMobile ? window.useMobile() : false;

  const [idx, setIdx] = React.useState(0);   // active panel
  const [t, setT] = React.useState(0);        // scrub progress within active panel (0–1) — for UI/cards
  const videoRefs = React.useRef([]);
  const tRef = React.useRef(0);               // live scrub target (read by the rAF loop)
  const idxRef = React.useRef(0);
  const animating = React.useRef(false);

  // Desktop scrub engine — wheel/keys drive tRef; crossing 1/0 advances panels.
  // Ref-driven so the listener subscribes once (no per-tick re-binding) and the
  // rAF easer always reads the freshest target.
  React.useEffect(() => {
    if (mobile) return undefined;
    const clamp = (v) => Math.max(0, Math.min(1, v));
    const step = (deltaY) => {
      if (animating.current) return;
      const i = idxRef.current, cur = tRef.current;
      if (cur >= 0.999 && deltaY > 0 && i < N - 1) { animating.current = true; idxRef.current = i + 1; tRef.current = 0; setIdx(i + 1); setT(0); setTimeout(() => { animating.current = false; }, 680); return; }
      if (cur <= 0.001 && deltaY < 0 && i > 0)     { animating.current = true; idxRef.current = i - 1; tRef.current = 1; setIdx(i - 1); setT(1); setTimeout(() => { animating.current = false; }, 680); return; }
      const nt = clamp(cur + deltaY / SCRUB_SENSITIVITY);
      tRef.current = nt; setT(nt);
    };
    const onWheel = (ev) => { ev.preventDefault(); step(ev.deltaY); };
    const onKey = (ev) => {
      if (ev.key === 'ArrowRight' || ev.key === 'ArrowDown') step(SCRUB_SENSITIVITY * 0.5);
      if (ev.key === 'ArrowLeft'  || ev.key === 'ArrowUp')   step(-SCRUB_SENSITIVITY * 0.5);
    };
    window.addEventListener('wheel', onWheel, { passive: false });
    window.addEventListener('keydown', onKey);
    return () => { window.removeEventListener('wheel', onWheel); window.removeEventListener('keydown', onKey); };
  }, [mobile, N]);

  // rAF easer — continuously slides the active video's currentTime toward the
  // scrub target. GOP=1 clips make every frame seekable, so this reads as smooth
  // playback rather than keyframe snapping. Mounts once (reads refs).
  React.useEffect(() => {
    if (mobile) return undefined;
    let raf;
    const tick = () => {
      const i = idxRef.current;
      const p = panels[i];
      const v = videoRefs.current[i];
      if (p && p.src && v && v.readyState >= 2) {
        const dur = p.cap ? Math.min(p.cap, v.duration || p.cap) : (v.duration || 0);
        if (dur > 0) {
          const target = tRef.current * dur;
          const c = v.currentTime;
          const d = target - c;
          if (Math.abs(d) > 0.002) { try { v.currentTime = c + d * 0.1; } catch (e) {} }
        }
      }
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [mobile, panels]);

  // Preload the ACTIVE panel immediately; defer neighbors to idle so first paint
  // isn't competing for bandwidth. Others stay 'none'. Posters cover any gap.
  React.useEffect(() => {
    if (mobile) return undefined;
    idxRef.current = idx;
    const up = (i) => { const p = panels[i]; const v = videoRefs.current[i]; if (p && p.src && v && v.preload !== 'auto') { v.preload = 'auto'; try { v.load(); } catch (e) {} } };
    up(idx);
    const idle = window.requestIdleCallback || ((cb) => setTimeout(cb, 700));
    const id = idle(() => { up(idx - 1); up(idx + 1); });
    return () => { if (window.cancelIdleCallback && typeof id === 'number') try { window.cancelIdleCallback(id); } catch (e) {} };
  }, [idx, mobile, panels]);

  // Advance one panel (intro "Enter →" + general use). Desktop drives the
  // scrub index; mobile scrolls the swipe strip.
  const advance = React.useCallback(() => {
    if (mobile) { const el = document.querySelector('.deck-mobile'); if (el) el.scrollBy({ left: el.clientWidth, behavior: 'smooth' }); }
    else { setIdx(i => { const n = Math.min(i + 1, N - 1); idxRef.current = n; tRef.current = 0; return n; }); setT(0); }
  }, [mobile, N]);

  // ── Mobile: swipe-snap poster strip (no video) ──
  if (mobile) {
    return (
      <div className="deck-mobile" style={{ display: 'flex', overflowX: 'auto', scrollSnapType: 'x mandatory',
        WebkitOverflowScrolling: 'touch', height: '100dvh', scrollbarWidth: 'none' }}>
        {panels.map((p) => (
          <section key={p.key} style={{ position: 'relative', flex: '0 0 100%', height: '100dvh',
            scrollSnapAlign: 'start', overflow: 'hidden', background: p.footer ? 'transparent' : '#1A1A1A' }}>
            {p.footer
              ? <DeckFooterPanel FooterCmp={FooterCmp} goTo={goTo} openNewsletter={openNewsletter} />
              : (<>
                  <img src={p.mobilePoster || p.poster} alt="" loading="lazy" decoding="async" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%',
                    objectFit: 'cover', objectPosition: p.mobilePos || 'center', transform: `scale(${DECK_OVERSCAN})`, display: 'block' }} />
                  <div style={{ position: 'absolute', inset: 0, background: 'linear-gradient(180deg,rgba(0,0,0,.15),rgba(0,0,0,.35))' }} />
                  <div className="deck-vignette" />
                  <DeckTitle panel={p} onAdvance={advance} />
                </>)}
          </section>
        ))}
      </div>
    );
  }

  // ── Desktop: horizontal slide deck with per-panel scrub ──
  return (
    <div style={{ position: 'fixed', inset: 0, overflow: 'hidden', background: '#0A0A0A', zIndex: 1 }}>
      <div style={{ display: 'flex', width: N * 100 + 'vw', height: '100%',
        transform: `translateX(-${idx * 100}vw)`, transition: 'transform .62s cubic-bezier(.7,0,.2,1)' }}>
        {panels.map((p, i) => (
          <section key={p.key} style={{ position: 'relative', flex: '0 0 100vw', height: '100%',
            overflow: 'hidden', background: p.footer ? 'transparent' : '#0A0A0A' }}>
            {p.footer
              ? <DeckFooterPanel FooterCmp={FooterCmp} goTo={goTo} openNewsletter={openNewsletter} />
              : (<>
                  <img src={p.poster} alt="" aria-hidden="true" loading={i === 0 ? 'eager' : 'lazy'} decoding="async"
                    style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover',
                      transform: `scale(${DECK_OVERSCAN})`, display: 'block', zIndex: 0 }} />
                  <video ref={el => videoRefs.current[i] = el} src={p.src} muted playsInline preload="none"
                    poster={p.poster}
                    style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover',
                      transform: `scale(${DECK_OVERSCAN})`, display: 'block', zIndex: 1 }} />
                  <div style={{ position: 'absolute', inset: 0, zIndex: 2,
                    background: 'linear-gradient(180deg,rgba(0,0,0,.12),rgba(0,0,0,.3))' }} />
                  <div className="deck-grain" />
                  <div className="deck-vignette" />
                  <div style={{ position: 'relative', zIndex: 3, height: '100%' }}>
                    <DeckTitle panel={p} onAdvance={advance} />
                  </div>
                </>)}
          </section>
        ))}
      </div>

      {/* progress dots (bottom-left, clear of the centered WhatsApp/cookie cluster) */}
      <div style={{ position: 'fixed', bottom: 28, left: 30, display: 'flex', gap: 10, zIndex: 80 }}>
        {panels.map((p, i) => (
          <span key={p.key} style={{ width: i === idx ? 22 : 7, height: 7, borderRadius: 4,
            background: i === idx ? 'var(--gold,#c6a86b)' : 'rgba(255,255,255,.35)', transition: 'all .3s' }} />
        ))}
      </div>
    </div>
  );
}

// Final panel — footer link columns in a cream box over the marble background.
function DeckFooterPanel({ FooterCmp, goTo, openNewsletter }) {
  return (
    <div className="deck-footer-panel" style={{ position: 'absolute', inset: 0, overflowY: 'auto',
      display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 'clamp(24px,4vw,64px)' }}>
      <div className="deck-footer-card" style={{ width: 'min(1100px,92vw)', background: 'rgba(244,239,229,.94)',
        border: '.5px solid rgba(26,26,26,.14)', borderRadius: 2, padding: 'clamp(28px,4vw,64px)',
        boxShadow: '0 40px 120px rgba(0,0,0,.28)' }}>
        {FooterCmp ? <FooterCmp openNewsletter={openNewsletter} goTo={goTo} /> : null}
      </div>
    </div>
  );
}

Object.assign(window, { HomeDeck });
