/* media.jsx — Media: YouTube video tiles + photo gallery with lightbox */
const { useState: _mState, useEffect: _mEffect, useCallback: _mCb, useRef: _mRef } = React;

/* Getty Images embed — injects Getty's own widget (their license requires the
   branded iframe + attribution). The anchor is injected via innerHTML so Getty's
   widgets.js can swap it for an iframe without React fighting the DOM change. The
   fixed-size widget is uniformly scaled (contain + centered) to fit a responsive
   tile-sized cell so it sits among the gallery photos. */
function GettyEmbed({ id, sig, items, w, h, caption = false, cellAspect }) {
  const cellRef = _mRef(null);
  const holdRef = _mRef(null);
  const nativeW = parseInt(w, 10) || 594;
  const nativeH = parseInt(h, 10) || 403;

  // inject the Getty anchor + load the widget once
  _mEffect(() => {
    const el = holdRef.current;
    if (!el) return;
    el.innerHTML =
      `<a id='${id}' class='gie-single' href='https://www.gettyimages.com/detail/${items}' target='_blank' rel='noopener' ` +
      `style='color:#a7a7a7;text-decoration:none;font-weight:normal !important;border:none;display:inline-block;'>Embed from Getty Images</a>`;
    window.gie = window.gie || function (c) { (window.gie.q = window.gie.q || []).push(c); };
    if (!document.querySelector('script[data-getty]')) {
      const sc = document.createElement('script');
      sc.src = '//embed-cdn.gettyimages.com/widgets.js';
      sc.async = true; sc.charset = 'utf-8'; sc.setAttribute('data-getty', '1');
      document.body.appendChild(sc);
    }
    window.gie(function () {
      window.gie.widgets.load({ id, sig, w, h, items, caption, tld: 'com', is360: false });
    });
  }, [id, sig, items, w, h, caption]);

  // scale the fixed widget to fit (contain) the responsive cell, recomputed on resize
  _mEffect(() => {
    const cell = cellRef.current, hold = holdRef.current;
    if (!cell || !hold) return;
    const fit = () => {
      const cw = cell.clientWidth, ch = cell.clientHeight;
      const scale = Math.min(cw / nativeW, ch / nativeH);
      // center horizontally, but top-align vertically so images of slightly different
      // native heights all line up at the top (no "sitting lower" offset)
      const tx = (cw - nativeW * scale) / 2, ty = 0;
      hold.style.transform = `translate(${tx}px, ${ty}px) scale(${scale})`;
    };
    fit();
    const ro = new ResizeObserver(fit);
    ro.observe(cell);
    return () => ro.disconnect();
  }, [nativeW, nativeH]);

  return (
    <div ref={cellRef} className="relative overflow-hidden ring-1 ring-white/10"
         style={{ width: '100%', aspectRatio: cellAspect || `${nativeW} / ${nativeH}`, background: '#060607' }}>
      <div ref={holdRef} className="gie-embed absolute left-0 top-0"
           style={{ width: nativeW, height: nativeH, transformOrigin: 'top left' }} />
    </div>
  );
}

const ytThumb = (id, hi) => `https://img.youtube.com/vi/${id}/${hi ? 'maxresdefault' : 'hqdefault'}.jpg`;

function VideoTile({ v, large, playing, onPlay }) {
  const open = () => {
    if (v.youtube) onPlay();
    else window.open('https://www.youtube.com/results?search_query=' + encodeURIComponent('Billy Joel ' + v.title + ' 1982'), '_blank', 'noopener');
  };
  const poster = v.poster || (v.youtube ? ytThumb(v.youtube, large) : '');
  return (
    <figure className={`group relative overflow-hidden ring-1 ring-white/12 ${large ? 'lg:col-span-2 lg:row-span-2' : ''}`}
            style={{ aspectRatio: large ? '16 / 10' : '16 / 9', background: '#060607' }}>
      {playing && v.youtube ? (
        <iframe className="absolute inset-0 h-full w-full" src={`https://www.youtube-nocookie.com/embed/${v.youtube}?autoplay=1&rel=0`}
                title={v.title} frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen></iframe>
      ) : (
        <button onClick={open} className="absolute inset-0 h-full w-full text-left" aria-label={`Play ${v.title}`}>
          <img src={poster} alt={v.title} className="absolute inset-0 h-full w-full object-cover"
               onError={(e) => { if (large && v.youtube && !e.currentTarget.dataset.fb) { e.currentTarget.dataset.fb = '1'; e.currentTarget.src = ytThumb(v.youtube, false); } }}
               style={{ filter: 'grayscale(0.45) contrast(1.05) brightness(0.55)', transition: 'transform 1.1s cubic-bezier(.16,.84,.36,1), filter .6s' }}
               loading="lazy" />
          <span className="absolute inset-0 transition-colors group-hover:bg-black/10" style={{ background: 'radial-gradient(60% 60% at 50% 45%, rgba(58,95,174,0.18), rgba(0,0,0,0.5) 75%)' }}></span>
          {/* play */}
          <span className="absolute left-1/2 top-1/2 grid -translate-x-1/2 -translate-y-1/2 place-items-center rounded-full border border-white/40 bg-black/30 backdrop-blur-sm transition-all duration-300 group-hover:scale-110 group-hover:border-white/80"
                style={{ width: large ? 84 : 60, height: large ? 84 : 60, boxShadow: '0 0 40px rgba(0,0,0,0.6)' }}>
            <span className="block border-y-transparent border-l-white" style={{ marginLeft: large ? 6 : 4, borderTopWidth: large ? 11 : 8, borderBottomWidth: large ? 11 : 8, borderLeftWidth: large ? 18 : 13, borderStyle: 'solid', borderTopColor: 'transparent', borderBottomColor: 'transparent' }}></span>
          </span>
          <span className="absolute inset-x-0 bottom-0 flex items-end justify-between gap-3 p-5">
            <span>
              <span className="flex items-center gap-2 font-mono text-[10px] uppercase tracking-[0.22em] text-ink-dim">
                <span className="inline-block h-[6px] w-[6px] rounded-full" style={{ background: 'var(--accent)' }}></span>{v.note}
              </span>
              <span className={`mt-1 block font-display uppercase leading-tight tracking-tight text-ink ${large ? 'text-[2rem]' : 'text-[1.4rem]'}`}>{v.title}</span>
              <span className="mt-1 block font-mono text-[10.5px] tracking-wide text-ink-faint">{v.meta}</span>
            </span>
          </span>
          {!v.youtube && (
            <span className="absolute right-4 top-4 border border-white/15 bg-black/55 px-2 py-1 font-mono text-[9px] uppercase tracking-[0.18em] text-ink-faint backdrop-blur-sm">Add embed ID</span>
          )}
        </button>
      )}
    </figure>
  );
}

function Lightbox({ photos, index, onClose, onNav }) {
  _mEffect(() => {
    const onKey = (e) => {
      if (e.key === 'Escape') onClose();
      if (e.key === 'ArrowRight') onNav(1);
      if (e.key === 'ArrowLeft') onNav(-1);
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose, onNav]);
  if (index == null) return null;
  const p = photos[index];
  return (
    <div className="fixed inset-0 z-[90] flex items-center justify-center" onClick={onClose} style={{ background: 'rgba(4,4,5,0.92)', backdropFilter: 'blur(6px)' }}>
      <button onClick={onClose} aria-label="Close" className="absolute right-5 top-5 grid h-10 w-10 place-items-center border border-white/30 text-ink transition-colors hover:border-white/55">✕</button>
      <button onClick={(e) => { e.stopPropagation(); onNav(-1); }} aria-label="Previous" className="absolute left-4 top-1/2 grid h-12 w-12 -translate-y-1/2 place-items-center border border-white/30 text-ink transition-colors hover:border-white/55 md:left-8">←</button>
      <button onClick={(e) => { e.stopPropagation(); onNav(1); }} aria-label="Next" className="absolute right-4 top-1/2 grid h-12 w-12 -translate-y-1/2 place-items-center border border-white/30 text-ink transition-colors hover:border-white/55 md:right-8">→</button>
      <figure className="max-h-[82vh] max-w-[88vw]" onClick={(e) => e.stopPropagation()}>
        <img src={p.src} alt={p.caption} className="max-h-[74vh] max-w-[88vw] object-contain ring-1 ring-white/12" />
        <figcaption className="mt-4 flex items-center justify-between gap-4 font-mono text-[11px] uppercase tracking-[0.16em] text-ink-faint">
          <span className="text-ink-dim">{p.caption}</span>
          <span>{String(index + 1).padStart(2, '0')} / {String(photos.length).padStart(2, '0')}</span>
        </figcaption>
      </figure>
    </div>
  );
}

function MediaToggle({ view, onChange }) {
  const opts = [{ id: 'video', label: 'Videos' }, { id: 'photos', label: 'Photos' }];
  const idx = Math.max(0, opts.findIndex((o) => o.id === view));
  return (
    <div className="relative grid w-full max-w-[320px] grid-cols-2 rounded-full border border-white/12 bg-coal-800 p-1"
         role="tablist" aria-label="Media view">
      <span className="absolute inset-y-1 left-1 rounded-full"
            style={{ width: 'calc(50% - 0.25rem)', transform: `translateX(${idx * 100}%)`,
              background: 'linear-gradient(180deg,var(--accent),var(--accent-deep))', boxShadow: '0 0 18px var(--accent-glow)',
              transition: 'transform 300ms cubic-bezier(.16,.84,.36,1)' }}></span>
      {opts.map((o) => (
        <button key={o.id} role="tab" aria-selected={view === o.id} onClick={() => onChange(o.id)}
                className="relative z-10 px-4 py-2.5 text-center font-mono text-[10.5px] uppercase tracking-[0.2em] transition-colors duration-300 sm:text-[11px]"
                style={{ color: view === o.id ? '#fff' : 'var(--ink-faint)' }}>
          {o.label}
        </button>
      ))}
    </div>
  );
}

function Media() {
  const { videos, photos, gettyPhotos = [] } = window.MEDIA;
  const [lb, setLb] = _mState(null);
  const [view, setView] = _mState('video');
  const [playingIdx, setPlayingIdx] = _mState(null);
  const nav = _mCb((d) => setLb((i) => (i == null ? i : (i + d + photos.length) % photos.length)), [photos.length]);
  const changeView = (v) => { setView(v); if (v !== 'video') setPlayingIdx(null); };

  return (
    <section id="media" className="relative border-t border-white/[0.06] bg-coal-800">
      <div className="mx-auto w-full max-w-[1320px] px-6 py-28 md:px-10 md:py-40">
        <SectionHead index="05 / Media" kicker="Footage & photography"
          title={<>The media archive: <span className="accent-word">Screen-matched evidence.</span></>}
          sub="Performance footage from the 1982 tour and close-up gallery. Tap a frame to watch; tap a photograph to enlarge." />

        <div className="mb-9 flex justify-center md:mb-12" data-reveal>
          <MediaToggle view={view} onChange={changeView} />
        </div>

        {/* videos — featured tile, then a labeled rule, then the rest */}
        {view === 'video' && (
          <React.Fragment>
            <VideoTile v={videos[0]} large playing={playingIdx === 0} onPlay={() => setPlayingIdx(0)} />
            {videos.length > 1 && (
              <React.Fragment>
                <div className="mt-12 mb-5 flex items-center gap-4">
                  <span className="font-mono text-[10px] uppercase tracking-[0.2em] text-ink-faint">Performances</span>
                  <span className="h-px flex-1" style={{ background: 'var(--line)' }}></span>
                </div>
                <div className="grid grid-cols-1 gap-px sm:grid-cols-2 lg:grid-cols-3">
                  {videos.slice(1).map((v, i) => (
                    <VideoTile key={v.youtube || v.title} v={v} playing={playingIdx === i + 1} onPlay={() => setPlayingIdx(i + 1)} />
                  ))}
                </div>
              </React.Fragment>
            )}
          </React.Fragment>
        )}

        {/* photos */}
        {view === 'photos' && (
          <div className="grid grid-cols-2 gap-px md:grid-cols-4">
            {/* per-photo crop = focal (object-position pan) + zoom (the CSS `scale` property, ≥1);
                the hover `transform: scale(1.05)` composes on top of that base zoom. Values are
                authored via tools/media-editor.html. */}
            <style>{`.media-tile:hover img{ transform: scale(1.05); }`}</style>
            {photos.map((p, i) => (
              <button key={p.src} onClick={() => setLb(i)}
                className="media-tile group relative overflow-hidden ring-1 ring-white/10" style={{ aspectRatio: '1 / 1', background: '#060607' }}>
                <img src={p.src} alt={p.caption} loading="lazy"
                     className="absolute inset-0 h-full w-full object-cover transition-transform duration-700"
                     style={{ filter: 'grayscale(0.3) contrast(1.04)', objectPosition: p.focal || '50% 50%', transformOrigin: p.focal || '50% 50%', scale: String(p.zoom || 1) }} />
                <span className="absolute inset-0 transition-colors group-hover:bg-black/0" style={{ background: 'linear-gradient(180deg,rgba(0,0,0,0) 50%,rgba(0,0,0,0.7) 100%)' }}></span>
                <span className="absolute left-3 top-3 font-mono text-[9px] uppercase tracking-[0.18em] text-ink-faint opacity-0 transition-opacity group-hover:opacity-100">{p.tag}</span>
                <span className="absolute inset-x-0 bottom-0 p-3 text-left font-mono text-[10px] leading-snug tracking-wide text-ink-dim opacity-0 transition-opacity duration-300 group-hover:opacity-100">{p.caption}</span>
                <span className="absolute right-3 top-3 grid h-7 w-7 place-items-center border border-white/20 bg-black/40 text-ink opacity-0 backdrop-blur-sm transition-opacity group-hover:opacity-100">⤢</span>
              </button>
            ))}
          </div>
        )}

        {/* Getty Images embeds — licensed widgets, grouped by orientation so rows
            stay even; each cell sized to one photo tile and left-aligned */}
        {view === 'photos' && gettyPhotos.length > 0 && (() => {
          const landscape = gettyPhotos.filter((g) => (parseInt(g.w, 10) || 0) >= (parseInt(g.h, 10) || 0));
          const portrait = gettyPhotos.filter((g) => (parseInt(g.w, 10) || 0) < (parseInt(g.h, 10) || 0));
          const groupAspect = (grp) => (grp[0] ? `${parseInt(grp[0].w, 10)} / ${parseInt(grp[0].h, 10)}` : undefined);
          return (
            <React.Fragment>
              <div className="mt-12 mb-5 flex items-center gap-4">
                <span className="font-mono text-[10px] uppercase tracking-[0.2em] text-ink-faint">From Getty Images</span>
                <span className="h-px flex-1" style={{ background: 'var(--line)' }}></span>
              </div>
              {[landscape, portrait].map((grp, gi) => grp.length > 0 && (
                <div key={gi} className="mt-px grid grid-cols-2 gap-px md:grid-cols-4">
                  {grp.map((g) => <GettyEmbed key={g.id} {...g} cellAspect={groupAspect(grp)} />)}
                </div>
              ))}
            </React.Fragment>
          );
        })()}

        <p className="mt-8 font-mono text-[10px] uppercase tracking-[0.2em] text-ink-faint">
          Performance footage embedded from YouTube · archival photography
        </p>
      </div>

      <Lightbox photos={photos} index={lb} onClose={() => setLb(null)} onNav={nav} />
    </section>
  );
}

Object.assign(window, { Media });
