/* ============================================================
   STORY — cinematic video scenes the moderator uploads, sequences and
   plays full-screen on the Main display like a movie.

   Videos are uploaded to Cloudflare Stream (adaptive HLS, same pipeline
   as the shop backdrops); only small scene metadata (title, order, the
   playback URL, poster, shown) travels in the synced game.story state.

   Four pieces (all hung on window.*):
     StorySetupPanel    — moderator prep: upload, sequence, rename
     StoryHostPanel     — run-game: thumbnails, dropdown, "Play on Main", "Showed"
     StoryMainView      — the full-screen movie (with audio) on the Main screen
     StoryPlayerOverlay — "look up at the Main screen" on player handsets
   ============================================================ */
const { useState: useS_st, useEffect: useE_st, useRef: useR_st } = React;

/* ---------- 1 · SETUP: upload + sequence + rename ---------- */
function StorySetupPanel({ game }){
  const scenes = (game.story && game.story.scenes) || [];
  const fileRef = useR_st(null);
  const [busy, setBusy] = useS_st('');
  const [err, setErr]   = useS_st('');

  const onPick = async (files)=>{
    if(!files || !files.length) return;
    setErr('');
    for(const f of Array.from(files)){
      if(!f.type || f.type.indexOf('video/')!==0){ setErr('Story scenes must be video files.'); continue; }
      setBusy(f.name);
      try{
        if(!window.uploadAsset) throw new Error('Backend not available.');
        const assetId = await window.uploadAsset(f, { gameId:null, category:'map' });
        const id = Game.addStoryScene({ assetId });
        // watch Cloudflare for processing to finish → fill HLS src + poster
        if(window.watchAsset){
          const ch = window.watchAsset(assetId, (row)=>{
            Game.setStorySceneReady(id, row.playback_url, row.thumbnail_url);
            try{ window.sb && window.sb.removeChannel(ch); }catch(_){}
          });
        }
      }catch(e){ setErr((e && e.message) ? e.message : 'Upload failed — sign in and try again.'); }
    }
    setBusy('');
    if(fileRef.current) fileRef.current.value='';
  };

  return (
    <div className="setup-section story-setup">
      <div className="setup-section-head">
        <div>
          <span className="setup-kind-label" style={{color:'#7db2ff'}}>Story Scenes</span>
          <span className="setup-kind-sub">Cinematic videos — played full-screen on the Main display</span>
        </div>
        <button className="tiny-btn" onClick={()=>fileRef.current&&fileRef.current.click()} disabled={!!busy}>
          {busy ? 'Uploading…' : '⤓ Upload video'}
        </button>
        <input ref={fileRef} type="file" accept="video/*" multiple style={{display:'none'}} onChange={e=>onPick(e.target.files)}/>
      </div>
      {err && <div className="story-err">{err}</div>}
      {scenes.length===0
        ? <div className="muted setup-empty">No scenes yet. Each upload becomes Scene 1, Scene 2… — rename them to anything (e.g. “Prologue”).</div>
        : <div className="story-setup-list">
            {scenes.map((s,i)=><StorySetupRow key={s.id} scene={s} index={i} total={scenes.length}/>)}
          </div>}
    </div>
  );
}

function StorySetupRow({ scene, index, total }){
  const [editing, setEditing] = useS_st(false);
  const [title, setTitle] = useS_st(scene.title);
  useE_st(()=>{ if(!editing) setTitle(scene.title); }, [scene.title]);
  const ready = scene.status==='ready' && scene.src;
  const commit = ()=>{ Game.renameStoryScene(scene.id, title.trim()||scene.title); setEditing(false); };
  return (
    <div className="story-srow">
      <span className="story-seq">{index+1}</span>
      <div className="story-sthumb">{scene.poster ? <img src={scene.poster} alt=""/> : <span className="story-proc">{ready?'▶':'⏳'}</span>}</div>
      <div className="story-smeta">
        {editing
          ? <input className="tinput story-rename" autoFocus value={title} maxLength={48}
              onChange={e=>setTitle(e.target.value)} onBlur={commit}
              onKeyDown={e=>{ if(e.key==='Enter') commit(); if(e.key==='Escape'){ setTitle(scene.title); setEditing(false); } }}/>
          : <button className="story-stitle" onClick={()=>setEditing(true)} title="Rename scene">{scene.title} <span className="story-pencil">✎</span></button>}
        <span className={`story-sstatus ${ready?'ok':''}`}>{ready ? 'Ready' : 'Processing on Cloudflare…'}</span>
      </div>
      <div className="story-sactions">
        <button className="tiny-btn" disabled={index===0} onClick={()=>Game.reorderStoryScene(scene.id,-1)} title="Move up">↑</button>
        <button className="tiny-btn" disabled={index===total-1} onClick={()=>Game.reorderStoryScene(scene.id,1)} title="Move down">↓</button>
        <button className="tiny-btn danger-outline" onClick={()=>{ if(confirm('Remove this scene?')) Game.removeStoryScene(scene.id); }} title="Remove">×</button>
      </div>
    </div>
  );
}
window.StorySetupPanel = StorySetupPanel;

/* ---------- 2 · RUN-GAME host panel ---------- */
function StoryHostPanel({ game }){
  const scenes = (game.story && game.story.scenes) || [];
  const playing = game.story && game.story.playing;
  const [open, setOpen] = useS_st(null);   // scene id whose dropdown is open

  return (
    <div className="story-host">
      <div className="story-host-head">
        <h3 className="section-label" style={{margin:0}}><Icon name="book" size={15}/> Story · cinematic scenes</h3>
        {playing && <button className="story-stop-all" onClick={()=>Game.stopStoryScene()}>■ Stop</button>}
      </div>
      {scenes.length===0
        ? <p className="muted" style={{fontSize:'.78rem',textTransform:'none',letterSpacing:'.01em'}}>No story scenes yet. Upload them in <b>Game Setup &amp; Library</b>.</p>
        : <div className="story-host-grid">
            {scenes.map((s,i)=>{
              const isPlaying = playing===s.id;
              const ready = s.status==='ready' && s.src;
              return (
                <div key={s.id} className={`story-tile ${isPlaying?'playing':''} ${s.shown?'is-shown':''}`}>
                  {s.shown && <span className="story-shown-tag">✓ Showed</span>}
                  <button className="story-tile-thumb" disabled={!ready}
                    onClick={()=> ready && setOpen(open===s.id ? null : s.id)} title={ready?'Tap for options':'Still processing'}>
                    {s.poster ? <img src={s.poster} alt=""/> : <span className="story-proc">{ready?'▶':'⏳'}</span>}
                    {ready && <span className="story-play-ico">{isPlaying?'❚❚':'▶'}</span>}
                  </button>
                  <div className="story-tile-foot"><span className="story-tile-title">{i+1}. {s.title}</span></div>
                  {open===s.id && ready && (
                    <div className="story-dropdown">
                      {isPlaying
                        ? <button className="story-dd-btn stop" onClick={()=>{ Game.stopStoryScene(); setOpen(null); }}>■ Stop playback</button>
                        : <button className="story-dd-btn play" onClick={()=>{ Game.playStoryScene(s.id); setOpen(null); }}>▶ Play on Main screen</button>}
                    </div>
                  )}
                </div>
              );
            })}
          </div>}
    </div>
  );
}
window.StoryHostPanel = StoryHostPanel;

/* ---------- 3 · MAIN screen full-screen movie (with audio) ---------- */
function StoryMainView({ scene }){
  const vref = useR_st(null);
  useE_st(()=>{
    const v = vref.current; if(!v || !scene.src) return;
    let hls = null;
    const isHls = /\.m3u8(\?|$)/i.test(scene.src);
    // a movie plays WITH sound; if the browser blocks unmuted autoplay
    // (no prior gesture on this display) fall back to muted so it still runs.
    const play = ()=>{ const p = v.play(); if(p && p.catch) p.catch(()=>{ v.muted = true; const q=v.play(); if(q&&q.catch) q.catch(()=>{}); }); };
    try{ audio.music && audio.music(null); }catch(_){}   // duck the scene music
    if(isHls){
      if(window.Hls && window.Hls.isSupported()){
        hls = new window.Hls({ capLevelToPlayerSize:true });
        hls.loadSource(scene.src); hls.attachMedia(v);
        hls.on(window.Hls.Events.MANIFEST_PARSED, play);
      } else if(v.canPlayType('application/vnd.apple.mpegurl')){ v.src = scene.src; play(); }
    } else { v.src = scene.src; play(); }
    return ()=>{ if(hls) hls.destroy(); };
  }, [scene.src]);

  return (
    <div className="story-cinema">
      <video ref={vref} className="story-cinema-video" playsInline autoPlay preload="auto"
        poster={scene.poster||undefined} onEnded={()=>Game.stopStoryScene(true)}/>
      <div className="story-cinema-title">{scene.title}</div>
    </div>
  );
}
window.StoryMainView = StoryMainView;

/* ---------- 4 · PLAYER overlay — focus on the Main screen ---------- */
function StoryPlayerOverlay(){
  const game = useGame();
  const playing = game.story && game.story.playing;
  if(!playing) return null;
  const scene = (game.story.scenes||[]).find(s=>s.id===playing);
  return (
    <div className="story-focus">
      <div className="story-focus-inner animate-fade-rise">
        <div className="story-focus-ico">▶</div>
        <h2 className="display">Eyes on the big screen</h2>
        <p>{scene ? `“${scene.title}” is playing` : 'A scene is playing'} — watch the Main display.</p>
      </div>
    </div>
  );
}
window.StoryPlayerOverlay = StoryPlayerOverlay;
