// player.jsx — Muna story player (the heart). 3 visual directions via tw.playerStyle.
(function () {
  const T = window.T, { IconBtn, VoiceChip, ImgSlot } = window;
  const { useState, useEffect, useRef } = React;

  function fmt(s) { s = Math.max(0, Math.floor(s)); return Math.floor(s / 60) + ':' + String(s % 60).padStart(2, '0'); }

  function makeTranscript(s, v) {
    return [
      { t: 0, x: s.story },
      { t: 22, x: `여기, ${s.name}이 자리한 이 터는 처음부터 이 모습이 아니었다.` },
      { t: 48, x: '돌 하나, 기둥 하나에는 그것을 세운 사람들의 손길과 셈이 배어 있다.' },
      { t: 76, x: `${v.name}의 목소리로, 그 시간의 결을 천천히 따라가 본다.` },
      { t: 104, x: '눈앞의 단정한 비례는 우연이 아니라, 오래 다듬어진 약속의 결과다.' },
      { t: 138, x: '잠시 고개를 들어, 처마의 선이 하늘과 만나는 자리를 바라보자.' },
      { t: 172, x: '그 선을 따라가다 보면, 이 자리에 깃든 마음이 어렴풋이 만져진다.' },
      { t: 206, x: '이야기는 여기서 잠시 숨을 고른다. 당신의 걸음에 맞춰, 천천히.' },
    ];
  }

  function Player({ go, app, params, tw, set }) {
    const s = window.siteById(params.id) || window.SITES[0];
    const { v } = window.pickVoice(app);
    const lang = window.LANGS.find(l => l.code === app.lang) || window.LANGS[0];
    const DUR = 360;
    const lines = makeTranscript(s, v);
    const key = 'muna_pos_' + s.id;
    const [pos, setPos] = useState(() => Number(localStorage.getItem(key) || 0));
    const [playing, setPlaying] = useState(true);
    const [rate, setRate] = useState(1);
    const [showScript, setShowScript] = useState(tw.playerStyle === 'transcript');
    const [why, setWhy] = useState(false);
    const tick = useRef();

    useEffect(() => {
      if (!playing) return;
      tick.current = setInterval(() => setPos(p => {
        const n = p + 0.5 * rate;
        if (n >= DUR) { clearInterval(tick.current); setPlaying(false); setTimeout(() => go('postplay', { id: s.id }), 400); return DUR; }
        return n;
      }), 500);
      return () => clearInterval(tick.current);
    }, [playing, rate]);
    useEffect(() => { localStorage.setItem(key, String(Math.floor(pos))); }, [pos]);

    const activeLine = lines.reduce((a, l, i) => pos >= l.t ? i : a, 0);
    const pct = (pos / DUR) * 100;
    const style = tw.playerStyle || 'immersive';

    const ctl = { pos, DUR, playing, setPlaying, rate, setRate, setPos, pct, fmt };

    return (
      <div style={{ position: 'absolute', inset: 0, background: T.tealDeep, overflow: 'hidden',
        display: 'flex', flexDirection: 'column' }}>
        <div style={{ position: 'absolute', inset: 0, background:
          'radial-gradient(110% 55% at 50% 0%, rgba(198,154,62,.20), transparent 55%)' }} />

        {/* top bar */}
        <div style={{ position: 'relative', zIndex: 3, display: 'flex', alignItems: 'center',
          justifyContent: 'space-between', padding: '12px 18px' }}>
          <IconBtn name="chevronD" onClick={() => go('back')} bg="rgba(246,240,227,.1)" border="transparent" color={T.onDark} />
          <div style={{ textAlign: 'center' }}>
            <div style={{ fontFamily: T.sans, fontSize: 11, fontWeight: 700, letterSpacing: 1,
              color: T.gold, textTransform: 'uppercase' }}>지금 재생 중</div>
            <div style={{ fontFamily: T.sans, fontSize: 12.5, color: T.onDarkMuted, marginTop: 1 }}>{s.type}</div>
          </div>
          <IconBtn name="share" bg="rgba(246,240,227,.1)" border="transparent" color={T.onDark} />
        </div>

        {/* ── body by style ── */}
        {style === 'transcript'
          ? <TranscriptBody s={s} v={v} app={app} lines={lines} active={activeLine} onWhy={() => setWhy(true)} />
          : style === 'minimal'
          ? <MinimalBody s={s} v={v} app={app} onWhy={() => setWhy(true)} />
          : <ImmersiveBody s={s} v={v} app={app} lines={lines} active={activeLine}
              showScript={showScript} setShowScript={setShowScript} onWhy={() => setWhy(true)} />}

        {/* ── controls ── */}
        <Controls {...ctl} lang={lang} go={go} s={s}
          showScriptToggle={style === 'immersive'}
          onScript={() => setShowScript(v => !v)} scriptOn={showScript} />

        {why && <window.WhyMini v={v} onClose={() => setWhy(false)} />}
      </div>
    );
  }

  // ── immersive ──
  function ImmersiveBody({ s, v, app, lines, active, showScript, setShowScript, onWhy }) {
    return (
      <div style={{ position: 'relative', zIndex: 3, flex: 1, minHeight: 0, display: 'flex',
        flexDirection: 'column', padding: '6px 24px 0' }}>
        {!showScript ? (
          <>
            <div style={{ flex: 1, minHeight: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <div style={{ width: '100%', maxWidth: 300, position: 'relative' }}>
                <ImgSlot label={s.full} h={300} r={24} tone="dark" />
                <div style={{ position: 'absolute', inset: 0, borderRadius: 24, boxShadow: 'inset 0 0 0 1px rgba(232,210,154,.25)' }} />
              </div>
            </div>
            <div style={{ paddingTop: 18 }}>
              <div style={{ fontFamily: T.sans, fontSize: 12.5, color: T.gold, fontWeight: 600 }}>{s.period}</div>
              <h2 style={{ fontFamily: T.display, fontSize: 28, letterSpacing: -.6, color: T.onDark, margin: '5px 0 12px' }}>{s.full}</h2>
              <VoiceChipDark app={app} onWhy={onWhy} />
            </div>
          </>
        ) : (
          <ScriptScroll s={s} lines={lines} active={active} />
        )}
      </div>
    );
  }

  // ── transcript-forward ──
  function TranscriptBody({ s, v, app, lines, active, onWhy }) {
    return (
      <div style={{ position: 'relative', zIndex: 3, flex: 1, minHeight: 0, display: 'flex',
        flexDirection: 'column', padding: '4px 24px 0' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 13, paddingBottom: 12 }}>
          <ImgSlot label="" h={56} style={{ width: 56, flexShrink: 0 }} r={14} tone="dark" />
          <div style={{ flex: 1, minWidth: 0 }}>
            <h2 style={{ fontFamily: T.display, fontSize: 19, letterSpacing: -.4, color: T.onDark, margin: 0 }}>{s.full}</h2>
            <button onClick={onWhy} style={{ background: 'none', border: 'none', padding: 0, cursor: 'pointer',
              display: 'flex', alignItems: 'center', gap: 5, marginTop: 3 }}>
              <Icon name="speaker" size={13} color={T.gold} />
              <span style={{ fontFamily: T.sans, fontSize: 12.5, color: T.gold, fontWeight: 600 }}>{v.name} · {v.role}</span>
            </button>
          </div>
        </div>
        <ScriptScroll s={s} lines={lines} active={active} />
      </div>
    );
  }

  // ── minimal ──
  function MinimalBody({ s, v, app, onWhy }) {
    return (
      <div style={{ position: 'relative', zIndex: 3, flex: 1, minHeight: 0, display: 'grid',
        placeItems: 'center', padding: '0 34px' }}>
        <div style={{ textAlign: 'center', width: '100%' }}>
          <div style={{ width: 168, height: 168, borderRadius: 99, position: 'relative', margin: '0 auto 30px',
            overflow: 'hidden', boxShadow: '0 30px 60px -20px rgba(0,0,0,.6), inset 0 0 0 1px rgba(232,210,154,.3)' }}>
            <ImgSlot label="" h={168} r={99} tone="dark" />
          </div>
          <div style={{ fontFamily: T.sans, fontSize: 12.5, color: T.gold, fontWeight: 600 }}>{s.period}</div>
          <h2 style={{ fontFamily: T.display, fontSize: 30, letterSpacing: -.7, color: T.onDark,
            margin: '6px 0 18px', whiteSpace: 'nowrap' }}>{s.full}</h2>
          <VoiceChipDark app={app} onWhy={onWhy} center />
        </div>
      </div>
    );
  }

  function VoiceChipDark({ app, onWhy, center }) {
    const { v } = window.pickVoice(app);
    return (
      <button onClick={onWhy} style={{ display: 'inline-flex', alignItems: 'center', gap: 10, cursor: 'pointer',
        background: 'rgba(246,240,227,.08)', border: '1px solid rgba(246,240,227,.16)', borderRadius: 99,
        padding: '7px 14px 7px 8px', margin: center ? '0 auto' : 0 }}>
        <div style={{ width: 32, height: 32, borderRadius: 99, background: T.tealEl, display: 'grid',
          placeItems: 'center', boxShadow: 'inset 0 0 0 1.5px ' + T.gold }}>
          <Icon name="speaker" size={16} color={T.gold} stroke={1.8} /></div>
        <div style={{ textAlign: 'left' }}>
          <div style={{ fontFamily: T.sans, fontSize: 10, fontWeight: 700, letterSpacing: .7,
            textTransform: 'uppercase', color: T.gold }}>AI 배정 보이스 · 왜?</div>
          <div style={{ fontFamily: T.sans, fontSize: 13.5, fontWeight: 600, color: T.onDark, whiteSpace: 'nowrap' }}>{v.name} · {v.role}</div>
        </div>
      </button>
    );
  }

  function ScriptScroll({ s, lines, active }) {
    const ref = useRef();
    useEffect(() => {
      const el = ref.current?.querySelector('[data-on="1"]');
      if (el && ref.current) ref.current.scrollTo({ top: el.offsetTop - 120, behavior: 'smooth' });
    }, [active]);
    return (
      <div ref={ref} style={{ flex: 1, minHeight: 0, overflowY: 'auto', scrollbarWidth: 'none',
        maskImage: 'linear-gradient(to bottom, transparent, #000 12%, #000 84%, transparent)',
        padding: '20px 0' }}>
        {lines.map((l, i) => (
          <p key={i} data-on={i === active ? '1' : '0'} style={{ fontFamily: T.display,
            fontSize: 20, lineHeight: 1.5, letterSpacing: -.3, margin: '0 0 20px',
            color: i === active ? T.onDark : 'rgba(246,240,227,.34)',
            transition: 'color .4s' }}>{l.x}</p>
        ))}
      </div>
    );
  }

  // ── shared controls ──
  function Controls({ pos, DUR, playing, setPlaying, rate, setRate, setPos, pct, lang, go, s, showScriptToggle, onScript, scriptOn }) {
    const rates = [1, 1.25, 1.5, 0.75];
    const seek = (e) => {
      const r = e.currentTarget.getBoundingClientRect();
      setPos(Math.min(DUR, Math.max(0, ((e.clientX - r.left) / r.width) * DUR)));
    };
    return (
      <div style={{ position: 'relative', zIndex: 3, padding: '14px 24px 24px', flexShrink: 0 }}>
        {/* progress */}
        <div onClick={seek} style={{ height: 22, display: 'flex', alignItems: 'center', cursor: 'pointer' }}>
          <div style={{ position: 'relative', width: '100%', height: 5, borderRadius: 9,
            background: 'rgba(246,240,227,.16)' }}>
            <div style={{ position: 'absolute', left: 0, top: 0, bottom: 0, width: pct + '%',
              background: T.gold, borderRadius: 9 }} />
            <div style={{ position: 'absolute', left: pct + '%', top: '50%', transform: 'translate(-50%,-50%)',
              width: 14, height: 14, borderRadius: 99, background: T.gold, boxShadow: '0 2px 6px rgba(0,0,0,.4)' }} />
          </div>
        </div>
        <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 4 }}>
          <span style={{ fontFamily: T.sans, fontSize: 12, color: T.onDarkMuted }}>{fmt(pos)}</span>
          <span style={{ fontFamily: T.sans, fontSize: 12, color: T.onDarkMuted }}>-{fmt(DUR - pos)}</span>
        </div>

        {/* transport */}
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 26, margin: '14px 0 16px' }}>
          <button onClick={() => setRate(rates[(rates.indexOf(rate) + 1) % rates.length])} style={{ width: 46,
            background: 'none', border: 'none', cursor: 'pointer', fontFamily: T.sans, fontSize: 14, fontWeight: 700,
            color: T.gold }}>{rate}x</button>
          <button onClick={() => setPos(Math.max(0, pos - 15))} style={{ background: 'none', border: 'none', cursor: 'pointer' }}>
            <Icon name="back15" size={30} color={T.onDark} /></button>
          <button onClick={() => setPlaying(!playing)} style={{ width: 70, height: 70, borderRadius: 99,
            background: T.gold, border: 'none', cursor: 'pointer', display: 'grid', placeItems: 'center',
            boxShadow: '0 12px 28px -8px rgba(198,154,62,.7)' }}>
            <Icon name={playing ? 'pause' : 'play'} size={28} color="#241c06" fill="#241c06" /></button>
          <button onClick={() => setPos(Math.min(DUR, pos + 15))} style={{ background: 'none', border: 'none', cursor: 'pointer' }}>
            <Icon name="fwd15" size={30} color={T.onDark} /></button>
          <button onClick={() => go('langPick')} style={{ width: 46, background: 'none', border: 'none',
            cursor: 'pointer', display: 'grid', placeItems: 'center' }}>
            <Icon name="globe" size={24} color={T.onDark} /></button>
        </div>

        {/* footer row */}
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
          <button onClick={() => go('langPick')} style={{ background: 'none', border: 'none', cursor: 'pointer',
            display: 'flex', alignItems: 'center', gap: 6 }}>
            <Icon name="globe" size={15} color={T.onDarkMuted} />
            <span style={{ fontFamily: T.sans, fontSize: 12.5, color: T.onDarkMuted }}>{lang.native}</span>
          </button>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
            <Icon name="lock" size={13} color={T.onDarkMuted} />
            <span style={{ fontFamily: T.sans, fontSize: 11.5, color: T.onDarkMuted }}>잠금화면 재생</span>
          </div>
          {showScriptToggle ? (
            <button onClick={onScript} style={{ background: scriptOn ? 'rgba(198,154,62,.2)' : 'none',
              border: '1px solid ' + (scriptOn ? T.gold : 'rgba(246,240,227,.2)'), borderRadius: 99,
              padding: '6px 12px', cursor: 'pointer', display: 'flex', alignItems: 'center', gap: 6 }}>
              <Icon name="list" size={14} color={scriptOn ? T.gold : T.onDarkMuted} />
              <span style={{ fontFamily: T.sans, fontSize: 12.5, fontWeight: 600,
                color: scriptOn ? T.gold : T.onDarkMuted }}>자막</span>
            </button>
          ) : <div style={{ width: 60 }} />}
        </div>
      </div>
    );
  }

  // why mini sheet (dark)
  window.WhyMini = function ({ v, onClose }) {
    return (
      <div onClick={onClose} style={{ position: 'absolute', inset: 0, zIndex: 40, background: 'rgba(10,18,15,.55)',
        display: 'flex', alignItems: 'flex-end', animation: 'munaFade .2s ease' }}>
        <div onClick={e => e.stopPropagation()} style={{ width: '100%', background: T.tealEl,
          borderRadius: '22px 22px 0 0', padding: '12px 24px 30px', animation: 'munaRise .3s ease',
          border: '1px solid rgba(232,210,154,.18)', borderBottom: 'none' }}>
          <div style={{ width: 40, height: 5, borderRadius: 9, background: 'rgba(246,240,227,.2)', margin: '0 auto 18px' }} />
          <window.Eyebrow color={T.gold}>왜 이 목소리인가요?</window.Eyebrow>
          <h3 style={{ fontFamily: T.display, fontSize: 22, letterSpacing: -.5, color: T.onDark, margin: '8px 0 5px' }}>
            {v.name} · {v.role}</h3>
          <div style={{ fontFamily: T.sans, fontSize: 13, color: T.onDarkMuted, marginBottom: 12 }}>{v.tone}</div>
          <p style={{ fontFamily: T.sans, fontSize: 14.5, lineHeight: 1.65, color: 'rgba(246,240,227,.9)', margin: 0 }}>{v.why}</p>
          <div style={{ marginTop: 22 }}><window.Btn full kind="gold" onClick={onClose}>알겠어요</window.Btn></div>
        </div>
      </div>
    );
  };

  window.Player = Player;
})();
