// prologue.jsx
// "PROLOGUE / ストーリー" section.
// Shown ABOVE the GymLeaders section.
// 3 main characters, each with an autoplaying .mp4 portrait.
// One character is "featured" at a time; auto-advances every 10 seconds.

const PROLOGUE_CHARS = [
{
  id: 'kokoha',
  epNo: '01',
  role: '主人公 / 中学生',
  classJa: '見習い保全士',
  name: '日向 心羽',
  yomi: 'ひなた ここは',
  age: 'NABI ID#0518',
  blurb: '失踪した母「海空(みそら)」を追い続ける14歳。\n母の残したゲノムキャプチャーを手に、旅へ出る。',
  emblems: 1,
  video: 'assets/story-kokoha.mp4',
  poster: 'assets/story-kokoha-poster.jpg',
  voice: 'assets/voice-kokoha.wav',
  cv: '羽澄 愛',
  accent: '#FFC21A'
},
{
  id: 'rui',
  epNo: '02',
  role: 'NABI 保全士',
  classJa: '正保全士',
  name: '神代 類',
  yomi: 'かみしろ るい',
  age: 'NABI ID#0421',
  blurb: 'スター保全士を志す、心羽の旅のパートナー。\n冷静沈着で、知識は折り紙付き。',
  emblems: 5,
  video: 'assets/story-rui.mp4',
  poster: 'assets/story-rui-poster.jpg',
  voice: 'assets/voice-rui.wav',
  cv: '嶺井一也(UMEX)',
  accent: '#4FA3D1'
},
{
  id: 'misora',
  epNo: '03',
  role: '伝説 / 心羽の母',
  classJa: 'スター保全士',
  name: '日向 海空',
  yomi: 'ひなた みそら',
  age: 'STATUS: MISSING',
  blurb: '「まだ見ぬ生き物を守る」と告げ、6年前に失踪。\nNABI設立期の最前線を駆け抜けた3代目スター保全士。\n国民からの人気が高く慕われている。',
  emblems: '?',
  video: 'assets/story-misora.mp4',
  poster: 'assets/story-misora-poster.jpg',
  voice: 'assets/voice-misora.mp3',
  cv: '青都 みなも',
  accent: '#E6421A'
}];


const PROLOGUE_SYNOPSIS = [
'人類はついにAGI（汎用人工知能）を産業ロボットに宿らせた。だがその代償は重かった――レアメタルを求めて掘り尽くされる山、乱立する小型原発と無秩序なメガソーラー、住民の声を無視して張り巡らされる送電網、そして守られなかったパリ協定における「1.5度目標」。',
'海ではサンゴが白く朽ち、森林火災は常態化、日本は熱帯の気候帯となった。動物たちの逃げ場は日ごとに細り、やがてコロナを超える大疫病が世界を襲う。',
'崩壊する生態系を前に、日本政府は環境省の外郭団体として「国立先進生物多様性機構（NABI）」を設立。最前線に立つ\u201C保全士\u201Dたちは、遺伝子情報をスキャンするだけで生命を取り込み、いつでもそのデータを呼び出せる装置――ゲノムキャプチャーを手に、消えゆく命の最後の砦として活動をしていた。',
'2048年、灼熱化した日本。中学生の日向 心羽（ひなた ここは）は、伝説のスター保全士の母・海空（みそら）が「まだ見ぬ生き物を守る」と告げて失踪したまま、6年の歳月を過ごしていた。',
'そんな時、「インベーダー4」が動き出す。地球史上6度目の――しかも\u201C大量絶滅\u201Dならぬ\u201C完全絶滅\u201Dを企み、人類だけの世界を作るため、生き物を次々と消し去っていく。',
'母が残したカードを手にした心羽（ここは）は、スター保全士を目指す、保全士・類（るい）と共に旅立つ。',
'これは、傷ついた地球が、生物多様性が、もう一度息を吹き返すまでの物語。'];


function PrologueCharCard({ c, isActive, index, onActivate }) {
  const videoRef = React.useRef(null);
  const audioRef = React.useRef(null);
  const [voicePlaying, setVoicePlaying] = React.useState(false);

  // Stop the voice clip whenever this card stops being the active one.
  React.useEffect(() => {
    if (!isActive && audioRef.current) {
      audioRef.current.pause();
      audioRef.current.currentTime = 0;
    }
  }, [isActive]);

  const toggleVoice = (e) => {
    e.stopPropagation();
    const a = audioRef.current;
    if (!a) return;
    if (a.paused) {
      a.currentTime = 0;
      const p = a.play();
      if (p && p.catch) p.catch(() => {});
    } else {
      a.pause();
    }
  };

  // Only the ACTIVE card decodes a video. Inactive cards detach their
  // source (releasing the hardware decoder) and fall back to a poster
  // image. This avoids the concurrent-decoder limit that left the
  // 2nd/3rd autoplaying videos black on some production browsers, and
  // guarantees a still image instead of a black frame if decode fails.
  React.useEffect(() => {
    const v = videoRef.current;
    if (!v) return;
    v.muted = true;
    v.defaultMuted = true;

    let cancelled = false;

    const tryPlay = () => {
      if (cancelled) return;
      const p = v.play();
      if (p && p.catch) p.catch(() => {});
    };

    if (isActive) {
      if (v.getAttribute('src') !== c.video) {
        v.setAttribute('src', c.video);
        v.load();
      }
      // Attempt immediately AND once the browser has buffered enough.
      // Production browsers (notably Safari) reject a play() issued before
      // the freshly-loaded source is ready, which previously left the
      // 2nd/3rd portraits frozen on their poster. Retrying on canplay
      // guarantees each portrait starts once its data arrives.
      tryPlay();
      v.addEventListener('loadeddata', tryPlay);
      v.addEventListener('canplay', tryPlay);
      return () => {
        cancelled = true;
        v.removeEventListener('loadeddata', tryPlay);
        v.removeEventListener('canplay', tryPlay);
      };
    } else {
      try { v.pause(); } catch (e) {}
      if (v.getAttribute('src')) {
        v.removeAttribute('src');
        v.load();
      }
    }
  }, [isActive, c.video]);

  return (
    <button
      type="button"
      className={`prologue-char ${isActive ? 'is-active' : ''}`}
      style={{ '--accent': c.accent }}
      onClick={() => onActivate(index)}
      aria-pressed={isActive}
      aria-label={`${c.name} のプロフィールを表示`}>
      <div className="prologue-char-frame">
        <div className="prologue-char-corner prologue-char-corner-tl" aria-hidden="true"></div>
        <div className="prologue-char-corner prologue-char-corner-tr" aria-hidden="true"></div>
        <div className="prologue-char-corner prologue-char-corner-bl" aria-hidden="true"></div>
        <div className="prologue-char-corner prologue-char-corner-br" aria-hidden="true"></div>

        <div className="prologue-char-video-wrap">
          <video
            ref={videoRef}
            className="prologue-char-video"
            poster={c.poster}
            muted
            loop
            playsInline
            preload="none" />
          <div className="prologue-char-scan" aria-hidden="true"></div>
          <div className="prologue-char-vignette" aria-hidden="true"></div>
        </div>

        <div className="prologue-char-status">{c.age}</div>
      </div>

      <div className="prologue-char-plate">
        <div className="prologue-char-role">{c.role}</div>
        <div className="prologue-char-name">
          <span className="prologue-char-class">{c.classJa}</span>
          <span className="prologue-char-given">{c.name}</span>
          <span className="prologue-char-yomi">（{c.yomi}）</span>
        </div>
        {c.voice ?
        <div className="prologue-char-voice-row">
          <span
            role="button"
            tabIndex={0}
            className={`prologue-char-voice ${voicePlaying ? 'is-playing' : ''}`}
            aria-label={`${c.name} のボイスを再生`}
            aria-pressed={voicePlaying}
            onClick={toggleVoice}
            onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { toggleVoice(e); } }}>
            <span className="prologue-char-voice-icon" aria-hidden="true">
              <span className="prologue-char-voice-wave"></span>
              <span className="prologue-char-voice-wave"></span>
              <span className="prologue-char-voice-wave"></span>
            </span>
            <span className="prologue-char-voice-label">{voicePlaying ? '再生中…' : 'ボイス再生'}</span>
          </span>
          <audio
            ref={audioRef}
            src={c.voice}
            preload="none"
            onPlay={() => setVoicePlaying(true)}
            onPause={() => setVoicePlaying(false)}
            onEnded={() => setVoicePlaying(false)} />
        </div> :
        null}
        {c.cv ? <div className="prologue-char-cv">CV. {c.cv}</div> : null}
        <p className="prologue-char-blurb">
          {c.blurb.split('\n').map((line, i) =>
          <React.Fragment key={i}>
              {line}
              {i < c.blurb.split('\n').length - 1 ? <br /> : null}
            </React.Fragment>
          )}
        </p>
        <div className="prologue-char-emblems">
          <span className="prologue-char-emblems-label">SHIELD EMBLEM</span>
          <span className="prologue-char-emblems-row">
            {typeof c.emblems === 'number' ?
            Array.from({ length: c.emblems }).map((_, i) =>
            <img key={i} src="assets/shield-emblem.png?v=2" alt="" className="prologue-char-emblem-icon" />
            ) :
            <img src="assets/shield-emblem.png?v=2" alt="" className="prologue-char-emblem-icon prologue-char-emblem-unknown" />
            }
            <span className="prologue-char-emblems-count">
              ×{c.emblems}
            </span>
          </span>
        </div>
      </div>
    </button>);

}

function Prologue() {
  const [active, setActive] = React.useState(0);
  const [synopsisOpen, setSynopsisOpen] = React.useState(false);

  // Highlight is driven purely by user tap; 心羽 (index 0) is selected first.
  const onActivate = (i) => {
    setActive(i);
  };

  return (
    <section className="prologue" id="prologue">
      <div className="prologue-bg" aria-hidden="true"></div>
      <div className="prologue-halftone" aria-hidden="true"></div>
      <div className="prologue-scanlines" aria-hidden="true"></div>

      <div className="container" style={{ position: 'relative', zIndex: 2 }}>
        <div className="prologue-header">
          <div className="prologue-meta">
            <span className="prologue-meta-tag">◤ STORY</span>
            <span className="prologue-meta-sep">|</span>
            <span className="prologue-meta-id">FILE-2048 / NABI ARCHIVE</span>
          </div>
          <h2 className="prologue-title">
            <span className="prologue-title-sub">2048年、灼熱化した日本——。生物多様性を守る戦いが今ここに。</span>
            <span className="prologue-title-main">絶滅の危機に立ち向かう、<br />最後の戦い。</span>
          </h2>
        </div>

        <div className="prologue-cast-wrap">
          <div className="prologue-cast-label">
            <span>MAIN CHARACTER</span>
            <span className="prologue-cast-label-counter">
              <span className="prologue-cast-label-cur">{String(active + 1).padStart(2, '0')}</span>
              <span>/</span>
              <span>{String(PROLOGUE_CHARS.length).padStart(2, '0')}</span>
            </span>
          </div>

          <div className="prologue-cast" data-active={active}>
            {PROLOGUE_CHARS.map((c, i) =>
            <PrologueCharCard
              key={c.id}
              c={c}
              index={i}
              isActive={i === active}
              onActivate={onActivate} />

            )}
          </div>

          <div className="prologue-progress" aria-hidden="true">
            {PROLOGUE_CHARS.map((c, i) =>
            <div
              key={c.id}
              className={`prologue-progress-bar ${i === active ? 'is-active' : ''}`}>
                <div className="prologue-progress-fill" />
              </div>
            )}
          </div>
          <div className="prologue-progress-hint">
            キャラクターをタップして切替
          </div>
        </div>

        <div className="prologue-synopsis-wrap">
          <div className="prologue-synopsis-label">
            <span className="prologue-synopsis-label-mono">STORY</span>
            <span className="prologue-synopsis-label-ja">あらすじ</span>
            <button
              type="button"
              className="prologue-synopsis-toggle"
              aria-expanded={synopsisOpen}
              onClick={() => setSynopsisOpen((v) => !v)}>
              {synopsisOpen ? '閉じる ▲' : '全文を読む ▼'}
            </button>
          </div>

          <div className={`prologue-synopsis-body ${synopsisOpen ? 'is-open' : 'is-collapsed'}`}>
            <div className="prologue-synopsis">
              <div className="prologue-synopsis-col">
                {PROLOGUE_SYNOPSIS.slice(0, 3).map((p, i) =>
                <p key={i} className={`prologue-synopsis-p ${i === 0 ? 'prologue-synopsis-lead' : ''}`}>{p}</p>
                )}
              </div>
              <div className="prologue-synopsis-col">
                {PROLOGUE_SYNOPSIS.slice(3).map((p, i) =>
                <p key={i} className="prologue-synopsis-p">{p}</p>
                )}
              </div>
            </div>
            <div className="prologue-gear">
              <div className="prologue-gear-head">
                <span className="prologue-gear-mono">KEY ITEM</span>
                <span className="prologue-gear-ja">物語で重要なグッズ</span>
              </div>
              <figure className="prologue-gear-figure">
                <img
                  className="prologue-gear-img"
                  src="assets/genome-lens.png"
                  alt="ゲノムレンズ — 生き物や植物をスキャンして、その遺伝情報をカードに変換するデバイス" />
              </figure>
            </div>
            {!synopsisOpen ? <div className="prologue-synopsis-fade" aria-hidden="true"></div> : null}
          </div>

          {!synopsisOpen ?
          <button
            type="button"
            className="prologue-synopsis-more"
            onClick={() => setSynopsisOpen(true)}>
            続きを読む ▼
          </button> :
          null}

        </div>
      </div>
    </section>);

}

function PrologueDisclaimer() {
  return (
    <section className="prologue-disclaimer-section" aria-label="フィクション注意書き">
      <div className="container">
        <div className="prologue-disclaimer">
          <div className="prologue-disclaimer-tag">FICTION / 注意書き</div>
          <p>
            ※ 物語・キャラクターはフィクションです。実在の人物・団体・国家機関・出来事・地名などとは一切関係ありません。
          </p>
        </div>
      </div>
    </section>);

}

Object.assign(window, { Prologue, PrologueCharCard, PrologueDisclaimer });