// 영어 롤플레이 — 본문 대화(.script) 안에서 그대로 진행하는 인라인 모드.
// 전체화면으로 넘어가지 않으므로 헤더·달력·탭·하단 오디오 플레이어가 그대로 남는다.
// (전체화면 버전은 RolePlay.jsx.bak.20260913에 보관)
//
// classic <script type="text/babel" src="pages/RolePlay.jsx"> 로 로드되므로 ES 모듈이 아니다.
// import/export를 쓰면 babel이 CommonJS(exports.default=...)로 바꾸는데 이 스크립트 환경엔
// exports 전역이 없어 런타임 에러가 난다 — 순수 전역 함수 선언만 쓴다.
// useState 등은 index.html의 메인 스크립트가 `const { useState } = React` 로 지역 변수화해서
// 쓰고 있어(그 스크립트 스코프 안에서만 유효) 이 파일에서 다시 꺼내 써야 한다. speakAs/apiFetch
// 처럼 function 선언으로 만들어진 전역은 그대로 재사용 가능.
const { useState, useRef, useEffect, useCallback } = React;

// ── 상태기계 ──────────────────────────────────────────────────
// lines는 DialogTab이 이미 mergeDialogLines()로 합친 배열 — 같은 화자가 연속으로 말하면
// 한 턴이고, 화자는 보통 A/B, 3인 대화면 C까지 나온다. getStartAt/getStopAt도 DialogTab의 것을 그대로 받아 쓴다
// (문장 앞뒤 여유 계산이 한 군데에만 있어야 재생 느낌이 어긋나지 않는다).
function useRolePlay({ lines, episodeId, seekAndPlay, pausePlayback, getStartAt, getStopAt }) {
  const [stage, setStage]       = useState('off');   // 'off' | 'picking' | 'playing' | 'done'
  const [myRole, setMyRole]     = useState('A');
  const [idx, setIdx]           = useState(0);
  const [revealed, setRevealed] = useState(false);
  const [showKo, setShowKo]     = useState(true);    // 내 차례에 한국어 번역을 힌트로 보여줄지
  const [autoPlay, setAutoPlay] = useState(true);    // 상대 대사 자동 재생 + 자동 진행
  const [optsOpen, setOptsOpen] = useState(false);   // ⚙️ 설정 패널 (.script 밖에 그려진다)

  const count    = lines.length;
  const cur      = lines[idx];
  const isLast   = idx === count - 1;
  const isMyTurn = !!cur && cur.speaker === myRole;
  // 맡을 수 있는 역할 — 대화에 나오는 화자 순서대로 (보통 A/B, 3인 대화면 A/B/C)
  const roles    = [...new Set(lines.map(l => l.speaker).filter(Boolean))].sort();

  // 타임스탬프가 없는 줄은 TTS로 읽는다 — 끝나는 시점을 알 수 없어 자동 진행은 하지 않는다
  const play = (i, onEnd) => {
    const line = lines[i];
    if (!line) return;
    if (seekAndPlay && line.timestamp_start != null) {
      seekAndPlay(getStartAt(i), getStopAt(i), onEnd);
    } else {
      speakAs(line.text, line.speaker);
    }
  };

  const stop = useCallback(() => { pausePlayback && pausePlayback(); }, [pausePlayback]);

  const advance = () => {
    setRevealed(false);
    if (idx + 1 >= count) setStage('done');
    else setIdx(idx + 1);
  };

  const actions = {
    open:    () => setStage('picking'),
    start:   (role) => { setMyRole(role); setIdx(0); setRevealed(false); setStage('playing'); },
    // 마지막 줄이 내 차례면 "말했어요"가 곧 마지막 동작 — 거기서 바로 완료로 넘어간다
    reveal:  () => { setRevealed(true); if (isLast) setStage('done'); },
    advance,
    skip:    () => { stop(); advance(); },
    // 마지막 줄은 자동 재생이 꺼져 있어도 다 들으면 완료로 넘어간다
    replay:  () => play(idx, autoPlay || isLast ? advance : undefined),  // 상대 대사 다시 듣기
    speak:   () => play(idx),                                            // 내 대사 원어민 발음
    finish:  () => { stop(); setStage('done'); },
    restart: () => { stop(); setIdx(0); setRevealed(false); setStage('playing'); },
    swap:    () => { stop(); setMyRole(r => roles[(roles.indexOf(r) + 1) % roles.length] ?? 'A'); setIdx(0); setRevealed(false); setStage('playing'); },
    exit:    () => { stop(); setStage('off'); setIdx(0); setRevealed(false); },
    setShowKo,
    setAutoPlay,
    toggleOpts: () => setOptsOpen(o => !o),
  };

  // 상대 차례로 들어가면 자동 재생 — 마지막 줄이면 재생이 끝나는 순간 완료 표시로 넘어간다
  // (advance()가 마지막에서 stage='done'으로 간다)
  useEffect(() => {
    if (stage !== 'playing') return;
    const line = lines[idx];
    if (!line || line.speaker === myRole) return;
    if (autoPlay) play(idx, advance);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [idx, stage, myRole, autoPlay, isLast]);

  // 회차를 옮기면 롤플레이는 처음 상태로 돌아간다
  useEffect(() => { setStage('off'); setIdx(0); setRevealed(false); }, [episodeId]);

  // 화면을 떠날 때 — 롤플레이 중이었을 때만 재생을 멈춘다.
  // (탭만 옮겨도 듣던 오디오가 끊기면 안 된다)
  const activeRef = useRef(false);
  activeRef.current = stage === 'playing';
  useEffect(() => () => { if (activeRef.current) pausePlayback && pausePlayback(); }, []);

  // 줄 하나의 상태 — DialogTab이 이걸로 클래스·본문·버튼을 정한다
  const rowState = (i) => {
    if (stage !== 'playing') return 'off';
    if (i < idx) return 'past';
    if (i > idx) return 'future';
    if (!isMyTurn) return 'theirs';
    return revealed ? 'mine-revealed' : 'mine-pending';
  };

  // 아직 안 나온 줄은 눌러도 재생되지 않고(들키지 않게), 내 차례는 말하기 전까지 재생하지 않는다
  const rowTapEnabled  = (i) => !['future', 'mine-pending'].includes(rowState(i));
  const rowPressEnabled = (i) => !['future', 'mine-pending'].includes(rowState(i));

  // 역할 고를 때 보여줄 미리보기 — 그 역할의 첫 대사
  const firstLineOf = (role) => lines.find(l => l.speaker === role)?.text ?? '';

  return { stage, myRole, idx, count, isLast, isMyTurn, showKo, autoPlay, optsOpen, roles,
           rowState, rowTapEnabled, rowPressEnabled, firstLineOf, ...actions };
}

// ── 역할 선택 팝업 ────────────────────────────────────────────
// 조각 저장 시트(.pick-*)와 같은 옷을 입는다 — 같은 자리에서 같은 방식으로 열리고 닫힌다.
function RolePlayRolePopup({ rp, cls }) {
  const openedAt = useRef(Date.now());
  // 버튼을 누른 손가락이 떼어지며 따라오는 click이 방금 뜬 팝업 위로 떨어지는 것을 막는다
  const settled = () => Date.now() - openedAt.current > 250;

  useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') rp.exit(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [rp.exit]);

  const roleBtn = (role) => (
    <button className="rp-role-btn" onClick={() => { if (settled()) rp.start(role); }}>
      <span className={`sbadge ${speakerBadgeCls(role)}`}>{role}</span>
      <span className="rp-role-name">{role} 역할로 연습</span>
      <span className="rp-role-ex">{rp.firstLineOf(role)}</span>
    </button>
  );

  return (
    <div className="pick-back" onClick={() => { if (settled()) rp.exit(); }}>
      <div className={`pick ${cls}`} onClick={e => e.stopPropagation()}
           role="dialog" aria-modal="true" aria-label="롤플레이 역할 선택">
        <div className="pick-hd">
          <span className="pick-title">🎭 롤플레이</span>
          <button className="pick-x" onClick={rp.exit} aria-label="닫기">✕</button>
        </div>
        <div className="pick-body">
          <div className="rp-ask">어떤 역할을 맡아볼까요?</div>
          <div className="rp-roles">{(rp.roles.length ? rp.roles : ['A', 'B']).map(r => <React.Fragment key={r}>{roleBtn(r)}</React.Fragment>)}</div>
        </div>
        <div className="pick-ft">
          <RolePlayOptions rp={rp} />
        </div>
      </div>
    </div>
  );
}

// 번역 힌트 / 자동 재생 — 팝업 아래쪽과 진행 중 ⚙️ 안에서 같은 모양으로 쓴다
function RolePlayOptions({ rp }) {
  const row = (label, on, toggle, hint) => (
    <div className="rp-opt">
      <span className="rp-opt-l">{label}<span className="rp-opt-h">{hint}</span></span>
      <button className={`rp-sw ${on ? 'on' : ''}`} onClick={() => toggle(v => !v)}>{on ? 'ON' : 'OFF'}</button>
    </div>
  );
  return (
    <>
      {row('번역 힌트', rp.showKo, rp.setShowKo, '내 차례에 한국어를 보여줍니다')}
      {row('자동 재생', rp.autoPlay, rp.setAutoPlay, '상대 대사를 듣고 자동으로 넘어갑니다')}
    </>
  );
}

// ── 진행 중 머리줄 (.script-hd 자리) ──────────────────────────
function RolePlayBar({ rp }) {
  return (
    <>
      <span className="t">🎭 롤플레이</span>
      <span className="rp-bar">
        <span className="rp-chip">나: {rp.myRole}</span>
        <span className="rp-chip">{rp.idx + 1} / {rp.count}</span>
        <button className={`rp-mini ${rp.optsOpen ? 'on' : ''}`} onClick={rp.toggleOpts} title="롤플레이 설정">⚙️</button>
        <button className="rp-mini" onClick={rp.exit} title="롤플레이 종료">✕</button>
      </span>
    </>
  );
}

// ⚙️로 여는 설정 패널 — .script가 overflow:hidden이라 박스 안에서는 잘린다. 박스 바로 위에 놓는다.
function RolePlayOptionsPanel({ rp }) {
  return <div className="rp-opts-panel"><RolePlayOptions rp={rp} /></div>;
}

// ── 줄 오른쪽 버튼 (🎵/💬 자리) ───────────────────────────────
function RolePlayRowControls({ rp, i }) {
  const st  = rp.rowState(i);
  const btn = (label, title, onClick, hot) => (
    <button className={`play-btn ${hot ? 'rp-hot' : ''}`} title={title}
      onClick={e => { e.stopPropagation(); onClick(); }}>{label}</button>
  );
  // 보통은 마지막 줄 재생이 끝나면 알아서 완료로 넘어간다. 이 버튼은 그게 일어나지 않는
  // 경우(자동 재생 OFF로 듣지 않고 넘길 때, 타임스탬프가 없어 TTS로 읽을 때)를 위한 마무리다.
  const nextBtn = rp.isLast
    ? btn('🏁', '마치기', rp.finish, true)
    : null;

  if (st === 'theirs') return (
    <>
      {btn('🔁', '다시 듣기', rp.replay)}
      {nextBtn ?? btn('⏭', '넘기기', rp.skip)}
    </>
  );
  if (st === 'mine-pending') return btn('🗣', '말했어요 — 원문 보기', rp.reveal, true);
  if (st === 'mine-revealed') return (
    <>
      {btn('🔊', '원어민 발음 듣기', rp.speak)}
      {nextBtn ?? btn('▶', '다음 줄로', rp.advance, true)}
    </>
  );
  return null;
}

// ── 완료 배너 ─────────────────────────────────────────────────
function RolePlayDone({ rp, cls }) {
  return (
    <div className="rp-done">
      <div className="rp-done-t">🎉 롤플레이 완료!</div>
      <div className="rp-done-acts">
        <button className={`btn fill ${cls}`} onClick={rp.swap}>🔁 역할 바꿔서 다시</button>
        <button className={`btn ${cls}`} onClick={rp.restart}>↺ 처음부터</button>
        <button className={`btn ${cls}`} onClick={rp.exit}>✕ 종료</button>
      </div>
    </div>
  );
}

// 롤플레이 CSS — DialogTab이 항상 한 번 렌더한다 (.rp-* 는 롤플레이 중에만 붙는 클래스라
// 평소 화면에는 아무 영향이 없다). 색은 전부 --ac 토큰이라 Easy/Power가 알아서 바뀐다.
function RolePlayStyles() {
  return <style>{ROLEPLAY_CSS}</style>;
}

const ROLEPLAY_CSS = `
/* 진행 중 머리줄 */
.rp-bar{display:flex;align-items:center;gap:6px;position:relative}
.rp-chip{font-size:10.5px;font-weight:800;letter-spacing:.03em;color:var(--ac-ink);background:var(--surface);
  border:1px solid var(--ac-line);border-radius:var(--pill);padding:2px 8px;font-variant-numeric:tabular-nums;white-space:nowrap}
.rp-mini{width:24px;height:24px;display:grid;place-items:center;border-radius:var(--r-xs);
  border:1px solid transparent;background:transparent;color:var(--ac-ink);font-size:12px;line-height:1}
.rp-mini:hover,.rp-mini.on{background:var(--surface);border-color:var(--ac-line)}
.rp-opts-panel{margin-bottom:10px;padding:6px 14px;background:var(--surface);
  border:1px solid var(--border);border-radius:var(--r);box-shadow:var(--sh-sm)}

/* 옵션 줄 (팝업 아래 / ⚙️ 안) */
.rp-opt{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:5px 0}
.rp-opt + .rp-opt{border-top:1px solid var(--border)}
.rp-opt-l{font-size:12.5px;font-weight:600;color:var(--text);display:flex;flex-direction:column;gap:1px}
.rp-opt-h{font-size:10.5px;font-weight:500;color:var(--muted2)}
.rp-sw{padding:3px 10px;border-radius:var(--pill);border:1px solid var(--border-strong);
  background:var(--surface);color:var(--muted);font-size:11px;font-weight:700;flex-shrink:0}
.rp-sw.on{background:var(--ac);border-color:var(--ac);color:#fff}

/* 대본 줄 상태 */
.srow.rp-past{opacity:.66}
.srow.rp-cur,.srow.rp-cur:hover{background:var(--ac-soft);box-shadow:inset 3px 0 0 var(--ac)}
.srow.rp-future .sen,.srow.rp-future .sko{filter:blur(5px);user-select:none;-webkit-user-select:none}
.rp-say{font-size:14.5px;font-weight:600;line-height:1.5;color:var(--ac-ink);background:var(--surface);
  border:1px dashed var(--ac);border-radius:var(--r-sm);padding:8px 11px}
.play-btn.rp-hot{color:var(--ac-ink);background:var(--surface);border:1px solid var(--ac-line)}
.play-btn.rp-hot:hover{background:var(--ac);border-color:var(--ac);color:#fff}

/* 역할 선택 팝업 */
.rp-ask{font-size:13.5px;font-weight:700;color:var(--text);margin-bottom:11px}
.rp-roles{display:flex;flex-direction:column;gap:9px}
.rp-role-btn{display:flex;align-items:center;gap:10px;width:100%;text-align:left;padding:12px 13px;
  border-radius:var(--r);border:1px solid var(--border-strong);background:var(--surface);box-shadow:var(--sh-xs);
  transition:border-color .15s,background .15s}
.rp-role-btn:hover{border-color:var(--ac);background:var(--ac-soft)}
.rp-role-name{font-size:14px;font-weight:700;color:var(--text);white-space:nowrap}
.rp-role-ex{flex:1;min-width:0;font-size:11.5px;color:var(--muted2);text-align:right;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* 완료 배너 */
.rp-done{margin:-2px 0 14px;padding:14px 16px;text-align:center;
  background:var(--ac-soft);border:1px solid var(--ac-line);border-radius:var(--r-lg)}
.rp-done-t{font-size:15px;font-weight:800;color:var(--ac-ink);margin-bottom:11px}
.rp-done-acts{display:flex;gap:7px;justify-content:center;flex-wrap:wrap}

@media(max-width:768px){
  .rp-role-ex{display:none}
  .rp-chip{padding:2px 7px}
}
`;
