// site-watch-live.jsx — Live broadcast section.
// Replaces WatchNowSection when festival.streaming.live.enabled === true.
// Hero: full-bleed image + YouTube embed centre-stage.
// Below: compact poster strip of tonight's strand films.

(function () {

const LIVE_COLORS = {
  Fiction:      { color:'#ff5c70', dark:'#3d0a12', text:'#fff' },
  Documentary:  { color:'#b66af5', dark:'#1e0a38', text:'#fff' },
  Animation:    { color:'#ffc823', dark:'#2c1d00', text:'#141318' },
  Experimental: { color:'#4dd8c0', dark:'#01211d', text:'#141318' },
  Awards:       { color:'#ffc823', dark:'#1a1400', text:'#141318' },
};

// Extract YouTube ID from any YouTube URL
function ytId(url) {
  if (!url) return null;
  const m = url.match(/(?:v=|youtu\.be\/|embed\/)([A-Za-z0-9_-]{11})/);
  return m ? m[1] : null;
}

// ── Vote confirmation modal (multiple Vote Now buttons sit close together in the rail,
// so we confirm which film before actually casting anything) ──────────────────
function VoteConfirmModal({ film, mode, busy, accentColor, textOn, onConfirm, onCancel }) {
  // Lock body scroll + pin it at the current offset while the modal is open. Without this,
  // mobile Safari (and some desktop edge cases) size a `position:fixed` overlay against the
  // *layout* viewport rather than the *visual* one once the page has been scrolled, so the
  // modal renders up near the document's top and the visible viewport has to be scrolled
  // back up to reach it. Freezing the body avoids that mismatch entirely.
  React.useEffect(() => {
    const scrollY = window.scrollY;
    const body = document.body;
    const prev = { position: body.style.position, top: body.style.top, left: body.style.left, right: body.style.right, width: body.style.width };
    body.style.position = 'fixed';
    body.style.top = `-${scrollY}px`;
    body.style.left = '0';
    body.style.right = '0';
    body.style.width = '100%';
    return () => {
      body.style.position = prev.position;
      body.style.top = prev.top;
      body.style.left = prev.left;
      body.style.right = prev.right;
      body.style.width = prev.width;
      window.scrollTo(0, scrollY);
    };
  }, []);

  return ReactDOM.createPortal(
    <div style={{ position:'fixed', inset:0, background:'rgba(14,13,18,.72)', zIndex:400, display:'flex', alignItems:'center', justifyContent:'center', padding:20 }} onClick={onCancel}>
      <div onClick={e => e.stopPropagation()} style={{ background:'#1a1820', border:'1px solid rgba(240,238,233,.14)', borderRadius:0, padding:'30px 32px', maxWidth:400, width:'100%', textAlign:'center' }}>
        <div style={{ fontFamily:'var(--mono)', fontSize:10, letterSpacing:'.16em', textTransform:'uppercase', color:'rgba(240,238,233,.45)', marginBottom:12 }}>Confirm your vote</div>
        <div style={{ fontFamily:'var(--display)', fontSize:24, textTransform:'uppercase', color:'#f0eee9', marginBottom:26, lineHeight:1.18, textWrap:'balance' }}>
          Vote for &ldquo;{film.title}&rdquo;?
        </div>
        <div style={{ display:'flex', gap:10, justifyContent:'center' }}>
          <button onClick={onCancel} disabled={busy}
            style={{ padding:'15px 26px', fontFamily:'var(--mono)', fontSize:12, letterSpacing:'.1em', textTransform:'uppercase', background:'transparent', border:'1px solid rgba(240,238,233,.3)', borderRadius:0, color:'#f0eee9', cursor:'pointer', transition:'border-color .16s' }}
            onMouseEnter={e => { e.currentTarget.style.borderColor = 'rgba(240,238,233,.7)'; }}
            onMouseLeave={e => { e.currentTarget.style.borderColor = 'rgba(240,238,233,.3)'; }}>
            Cancel
          </button>
          <button onClick={onConfirm} disabled={busy}
            style={{ padding:'15px 26px', fontFamily:'var(--mono)', fontSize:12, letterSpacing:'.1em', textTransform:'uppercase', background:accentColor, border:'none', borderRadius:0, color:textOn, fontWeight:700, cursor: busy ? 'default' : 'pointer', opacity: busy ? .7 : 1, transition:'filter .14s' }}
            onMouseEnter={e => { if (!busy) e.currentTarget.style.filter = 'brightness(1.12)'; }}
            onMouseLeave={e => { e.currentTarget.style.filter = 'none'; }}>
            {busy ? 'Voting…' : 'Yes, vote'}
          </button>
        </div>
      </div>
    </div>,
    document.body
  );
}

// ── Compact poster card ───────────────────────────────────────────────────────
function PosterCard({ film, accentColor, showVote, voted, onVoteClick, navigate }) {
  const poster = film.poster || (film.stillsImages && film.stillsImages[0] && film.stillsImages[0].url) || '';
  const title  = film.title || '';
  const dir    = Array.isArray(film.directors)
    ? film.directors.map(d => d.name || d).join(', ')
    : (film.directors || '');
  const [hov, setHov] = React.useState(false);

  return (
    <div style={{ flex:'none', width:148, cursor:'pointer' }}
      onClick={() => navigate && navigate('/film/' + film.id)}>
      {/* Poster */}
      <div style={{ width:148, height:210, overflow:'hidden', position:'relative', background:'#0e0d12' }}
        onMouseEnter={() => setHov(true)} onMouseLeave={() => setHov(false)}>
        {poster
          ? <img src={poster} alt={title} style={{
              width:'100%', height:'100%', objectFit:'cover', display:'block',
              transform: hov ? 'scale(1.04)' : 'scale(1)',
              transition:'transform .4s cubic-bezier(.2,.7,.3,1)',
              filter: hov ? 'brightness(.7)' : 'brightness(.88)',
            }} />
          : <div style={{ width:'100%', height:'100%', background:'#1a1820',
              display:'flex', alignItems:'center', justifyContent:'center' }}>
              <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="rgba(240,238,233,.2)" strokeWidth="1.2">
                <rect x="3" y="3" width="18" height="18"/><path d="M3 9h18M9 21V9"/>
              </svg>
            </div>
        }
        {/* Strand accent bar at bottom */}
        <div style={{ position:'absolute', bottom:0, left:0, right:0, height:3, background:accentColor, opacity:.9 }}></div>
        {hov && <div style={{ position:'absolute', inset:0, display:'flex', alignItems:'center', justifyContent:'center' }}>
          <div style={{ width:44, height:44, background:'rgba(255,255,255,.12)', border:'1.5px solid rgba(255,255,255,.8)',
            display:'flex', alignItems:'center', justifyContent:'center', backdropFilter:'blur(4px)' }}>
            <svg width="16" height="16" viewBox="0 0 24 24" fill="#fff"><path d="M8 5v14l11-7z"/></svg>
          </div>
        </div>}
      </div>
      {/* Title */}
      <div style={{ marginTop:10, paddingRight:4 }}>
        <div style={{ fontFamily:'var(--display)', fontSize:13, textTransform:'uppercase',
          letterSpacing:'-.01em', lineHeight:1.05, color:'var(--paper)',
          whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>
          {title}
        </div>
        {dir && <div style={{ fontFamily:'var(--mono)', fontSize:9.5, letterSpacing:'.06em',
          color:'rgba(240,238,233,.42)', marginTop:4, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>
          {dir}
        </div>}
        {showVote && (
          <button
            onClick={e => { e.stopPropagation(); if (!voted) onVoteClick(film); }}
            disabled={voted}
            style={{ marginTop:10, padding:'6px 14px', fontFamily:'var(--mono)', fontSize:9,
              letterSpacing:'.13em', textTransform:'uppercase',
              background: voted ? 'transparent' : accentColor,
              color: voted ? accentColor : (LIVE_COLORS[film.strand]?.text || '#fff'),
              border: voted ? `1px solid ${accentColor}` : 'none',
              cursor: voted ? 'default' : 'pointer',
              transition:'opacity .15s' }}
            onMouseEnter={e => { if (!voted) e.currentTarget.style.opacity='.78'; }}
            onMouseLeave={e => e.currentTarget.style.opacity='1'}>
            {voted ? '✓ Voted' : 'Vote Now →'}
          </button>
        )}
      </div>
    </div>
  );
}

// ── Main component ────────────────────────────────────────────────────────────
function WatchLiveSection({ navigate }) {
  const d         = useSite();
  const f         = d.festival || {};
  const str       = f.streaming || {};
  const live      = str.live    || {};
  const items     = live.items  || {};
  const activeKey = live.activeItem || 'Fiction';
  const item      = items[activeKey] || {};
  const isAwards  = activeKey === 'Awards';
  const sc        = LIVE_COLORS[activeKey] || LIVE_COLORS.Fiction;
  const votingOpen = !!f.votingOpen;
  const votingMode = f.voting?.mode || 'internal';
  const [confirmFilm, setConfirmFilm] = React.useState(null);
  const [votingBusy, setVotingBusy]   = React.useState(false);
  const [voteTick, setVoteTick]       = React.useState(0);

  const handleVoteClick = fl => setConfirmFilm(fl);
  const confirmColor = confirmFilm ? (LIVE_COLORS[confirmFilm.strand] || sc) : sc;
  const [blockedVote, setBlockedVote] = React.useState(false);
  const handleCancelVote = () => { if (!votingBusy) setConfirmFilm(null); };
  const handleConfirmVote = () => {
    const fl = confirmFilm;
    if (!fl) return;
    if (votingMode === 'external') {
      if (fl.voteLink) window.open(fl.voteLink, '_blank');
      setConfirmFilm(null);
      return;
    }
    setVotingBusy(true);
    window.castVote(fl.id, 'online', fl.year).then(res => {
      if (res.ok) { window.markVotedLocally(fl.id); }
      else if (res.duplicate) { window.markVotedLocally(fl.id); setBlockedVote(true); }
      setVotingBusy(false);
      setConfirmFilm(null);
      setVoteTick(t => t + 1);
    });
  };

  const videoId   = ytId(item.url);
  const heroImage = item.heroImage || '';
  const title     = item.title || (isAwards ? 'Paper Bird Awards Ceremony' : `${activeKey} · Live`);

  // Films for tonight's strand
  const currentYear = String(f.year || new Date().getFullYear());
  const strandFilms = isAwards
    ? (d.films || []).filter(fl => fl.status === 'published' && String(fl.year) === currentYear)
    : (d.films || []).filter(fl =>
        fl.status === 'published' &&
        String(fl.year) === currentYear &&
        fl.strand === activeKey
      );

  const trackRef = React.useRef(null);
  const [canPrev, setCanPrev] = React.useState(false);
  const [canNext, setCanNext] = React.useState(true);

  const updateArrows = () => {
    const t = trackRef.current; if (!t) return;
    setCanPrev(t.scrollLeft > 4);
    setCanNext(t.scrollLeft < t.scrollWidth - t.clientWidth - 4);
  };
  const scrollBy = dir => { trackRef.current?.scrollBy({ left: dir * 164 * 2, behavior:'smooth' }); };

  return (
    <div style={{ background:'#0e0d12', overflow:'hidden' }}>

      {/* ── Top strand accent bar ── */}
      <div style={{ height:4, background:sc.color, width:'100%' }}></div>

      {/* ── Hero: full-bleed image + YouTube player ── */}
      <div className="wl-hero-media" style={{ position:'relative', width:'100%', minHeight:'72vh',
        display:'flex', flexDirection:'column', justifyContent:'center',
        overflow:'hidden' }}>

        {/* Background image */}
        {heroImage
          ? <img src={heroImage} alt="" style={{
              position:'absolute', inset:0, width:'100%', height:'100%',
              objectFit:'cover', display:'block',
              filter:'brightness(.32) saturate(.7)'
            }} />
          : <div style={{ position:'absolute', inset:0,
              background:`radial-gradient(ellipse at 60% 40%, ${sc.dark} 0%, #0e0d12 70%)` }}></div>
        }

        {/* Grain texture overlay */}
        <div style={{ position:'absolute', inset:0, opacity:.04, pointerEvents:'none',
          backgroundImage:`url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")`,
          backgroundSize:'256px' }}></div>

        {/* Bottom gradient */}
        <div style={{ position:'absolute', bottom:0, left:0, right:0, height:'40%',
          background:'linear-gradient(to top, #0e0d12 0%, transparent 100%)', pointerEvents:'none' }}></div>

        {/* Content */}
        <div style={{ position:'relative', zIndex:2, width:'100%', padding:'clamp(32px,5vh,56px) 0 clamp(24px,4vh,44px)' }}>
          <div className="wrap">

            {/* Live badge */}
            <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:'clamp(18px,3vh,28px)' }}>
              <span style={{ width:9, height:9, borderRadius:'50%', background:'#ef4444',
                display:'inline-block', animation:'wl-dot 1.5s ease-in-out infinite' }}></span>
              <span style={{ fontFamily:'var(--mono)', fontSize:10, letterSpacing:'.22em',
                textTransform:'uppercase', color:'#ef4444' }}>
                Live Now &middot; {isAwards ? 'Paper Bird Awards' : activeKey}
              </span>
            </div>

            {/* YouTube player — centred */}
            {videoId ? (
              <div style={{ width:'100%', maxWidth:920, aspectRatio:'16/9',
                background:'#000', overflow:'hidden', marginBottom:'clamp(24px,4vh,40px)',
                boxShadow:'0 0 0 1px rgba(255,255,255,.06), 0 32px 80px rgba(0,0,0,.7)',
                marginLeft:'auto', marginRight:'auto' }}>
                <iframe
                  src={`https://www.youtube.com/embed/${videoId}?autoplay=0&rel=0&modestbranding=1`}
                  title={title}
                  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
                  allowFullScreen
                  style={{ width:'100%', height:'100%', border:'none', display:'block' }} />
              </div>
            ) : (
              <div style={{ width:'100%', maxWidth:920, aspectRatio:'16/9',
                background:'rgba(255,255,255,.03)', border:'1px solid rgba(255,255,255,.07)',
                display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center',
                gap:18, marginBottom:'clamp(24px,4vh,40px)',
                marginLeft:'auto', marginRight:'auto' }}>
                <svg width="52" height="52" viewBox="0 0 24 24" fill="none" stroke="rgba(240,238,233,.18)" strokeWidth="1">
                  <polygon points="5 3 19 12 5 21 5 3"/>
                </svg>
                <span style={{ fontFamily:'var(--mono)', fontSize:10, letterSpacing:'.2em',
                  textTransform:'uppercase', color:'rgba(240,238,233,.22)' }}>
                  Stream starting soon
                </span>
              </div>
            )}

            {/* Bottom row: title + CTA */}
            <div style={{ display:'flex', alignItems:'flex-end', justifyContent:'space-between',
              gap:20, flexWrap:'wrap' }}>
              <div>
                <div style={{ fontFamily:'var(--display)', fontSize:'clamp(32px,5.5vw,80px)',
                  textTransform:'uppercase', letterSpacing:'-.025em', lineHeight:.9,
                  color:'var(--paper)', textShadow:'0 2px 40px rgba(0,0,0,.6)' }}>
                  {title}
                </div>
              </div>
              <button
                onClick={() => navigate && navigate('/programme')}
                style={{ fontFamily:'var(--mono)', fontSize:10, letterSpacing:'.16em',
                  textTransform:'uppercase', padding:'13px 26px',
                  background:'transparent', border:`1px solid rgba(240,238,233,.3)`,
                  color:'var(--paper)', cursor:'pointer', whiteSpace:'nowrap',
                  transition:'border-color .16s, color .16s', flexShrink:0 }}
                onMouseEnter={e => { e.currentTarget.style.borderColor='var(--paper)'; }}
                onMouseLeave={e => { e.currentTarget.style.borderColor='rgba(240,238,233,.3)'; }}>
                View Programme →
              </button>
            </div>

          </div>
        </div>
      </div>

      {/* ── Tonight's films: compact poster strip ── */}
      {strandFilms.length > 0 && (
        <div style={{ paddingBottom:'clamp(40px,6vh,72px)' }}>

          {/* Poster rail header with arrows */}
          <div className="wrap">
            <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', gap:16, marginBottom:20, paddingTop:'clamp(28px,4vh,44px)' }}>
              <div style={{ display:'flex', alignItems:'center', gap:16 }}>
                <div style={{ width:3, height:22, background:sc.color, flexShrink:0 }}></div>
                <span style={{ fontFamily:'var(--mono)', fontSize:10, letterSpacing:'.22em',
                  textTransform:'uppercase', color:'rgba(240,238,233,.5)' }}>
                  {isAwards ? 'All films · Sixth Edition' : `Screening Tonight · ${activeKey}`}
                </span>
                <div style={{ width:60, height:'1px', background:'rgba(240,238,233,.08)' }}></div>
                <span style={{ fontFamily:'var(--mono)', fontSize:9, letterSpacing:'.12em',
                  color:'rgba(240,238,233,.28)', textTransform:'uppercase' }}>
                  {strandFilms.length} {strandFilms.length === 1 ? 'film' : 'films'}
                </span>
              </div>
              <div style={{ display:'flex', gap:8, flexShrink:0 }}>
                <button onClick={() => scrollBy(-1)} disabled={!canPrev}
                  style={{ width:40, height:40, borderRadius:'50%', border:'1px solid rgba(240,238,233,.2)',
                    background:'none', color:'var(--paper)', cursor:'pointer', display:'flex',
                    alignItems:'center', justifyContent:'center', transition:'.16s',
                    opacity: canPrev ? 1 : .25 }}>
                  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M15 18l-6-6 6-6"/></svg>
                </button>
                <button onClick={() => scrollBy(1)} disabled={!canNext}
                  style={{ width:40, height:40, borderRadius:'50%', border:'1px solid rgba(240,238,233,.2)',
                    background:'none', color:'var(--paper)', cursor:'pointer', display:'flex',
                    alignItems:'center', justifyContent:'center', transition:'.16s',
                    opacity: canNext ? 1 : .25 }}>
                  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M9 18l6-6-6-6"/></svg>
                </button>
              </div>
            </div>
          </div>

          {/* Poster rail */}
          <div className="wrap">
            <div style={{ position:'relative' }}>
            <div
              ref={trackRef}
              onScroll={updateArrows}
              style={{ display:'flex', gap:16, overflowX:'auto',
                padding:'4px 0 12px',
                scrollSnapType:'x proximity', scrollBehavior:'smooth',
                msOverflowStyle:'none', scrollbarWidth:'none' }}>
              {strandFilms.map(fl => {
                const showVote = votingOpen && (votingMode === 'internal' ? fl.voteEnabled : fl.voteLink);
                const voted = voteTick >= 0 && window.hasVotedLocally && window.hasVotedLocally(fl.id);
                return (
                  <div key={fl.id} style={{ scrollSnapAlign:'start', flexShrink:0 }}>
                    <PosterCard
                      film={fl}
                      accentColor={sc.color}
                      showVote={showVote}
                      voted={voted}
                      onVoteClick={handleVoteClick}
                      navigate={navigate}
                    />
                  </div>
                );
              })}
            </div>
            {/* Edge fades — separate overlay layers so opacity can transition smoothly;
                CSS mask-image swaps don't animate reliably across browsers. */}
            <div style={{ position:'absolute', top:0, bottom:12, left:0, width:90, pointerEvents:'none',
              background:'linear-gradient(to right, #0e0d12, transparent)',
              opacity: canPrev ? 1 : 0, transition:'opacity .35s ease' }} />
            <div style={{ position:'absolute', top:0, bottom:12, right:0, width:90, pointerEvents:'none',
              background:'linear-gradient(to left, #0e0d12, transparent)',
              opacity: canNext ? 1 : 0, transition:'opacity .35s ease' }} />
            </div>
          </div>

        </div>
      )}

      {confirmFilm && (
        <VoteConfirmModal film={confirmFilm} mode={votingMode} busy={votingBusy}
          accentColor={confirmColor.color} textOn={confirmColor.text}
          onConfirm={handleConfirmVote} onCancel={handleCancelVote} />
      )}
      {blockedVote && window.VoteBlockedModal && (
        <window.VoteBlockedModal onClose={() => setBlockedVote(false)} />
      )}

      <style>{`
        @keyframes wl-dot {
          0%,100% { opacity:1; box-shadow:0 0 0 0 rgba(239,68,68,.5); }
          50%      { opacity:.85; box-shadow:0 0 0 9px rgba(239,68,68,0); }
        }
        @media (max-width:640px) {
          .wl-grid { grid-template-columns: repeat(3, 1fr) !important; gap:12px !important; }
        }
      `}</style>
    </div>
  );
}

Object.assign(window, { WatchLiveSection });

})();
