// Activity components — Reading, Listening, Speaking, Writing, Vocab, Grammar
// Activities call window.__markActivityComplete?.(key) when finished.
// In Section 2 the helper is undefined, so the call is a harmless no-op.
function _done(key, onExit) {
  return () => { try { window.__markActivityComplete && window.__markActivityComplete(key); } catch(e){} onExit(); };
}

// ============ AUDIO PLAYER (segment-aware) ============
function AudioPlayer({ src, start, end, label }) {
  const ref = React.useRef(null);
  const [playing, setPlaying] = useState(false);
  const [rate, setRate] = useState(1);
  const [played, setPlayed] = useState(0); // play count

  React.useEffect(() => {
    const a = ref.current;
    if (!a) return;
    const onTime = () => {
      if (typeof end === "number" && a.currentTime >= end) {
        a.pause();
        setPlaying(false);
      }
    };
    const onEnd = () => setPlaying(false);
    a.addEventListener("timeupdate", onTime);
    a.addEventListener("ended", onEnd);
    return () => { a.removeEventListener("timeupdate", onTime); a.removeEventListener("ended", onEnd); };
  }, [end]);

  React.useEffect(() => {
    const a = ref.current;
    if (!a) return;
    a.playbackRate = rate;
  }, [rate]);

  function play() {
    const a = ref.current;
    if (!a) return;
    if (typeof start === "number") a.currentTime = start;
    a.play();
    setPlaying(true);
    setPlayed(p => p + 1);
  }
  function pause() {
    const a = ref.current;
    if (a) a.pause();
    setPlaying(false);
  }

  return (
    <div className="audio-placeholder">
      <audio ref={ref} src={src} preload="auto" />
      <button
        className={"audio-play-btn" + (playing ? " is-playing" : "")}
        onClick={playing ? pause : play}
        aria-label={playing ? "停止" : "再生"}
      >
        {playing ? "■" : "▶"}
      </button>
      <div className="audio-meta">
        <div className="audio-label">{label}</div>
        <div className="audio-controls">
          <button
            className={"rate-btn" + (rate === 1 ? " is-on" : "")}
            onClick={() => setRate(1)}
          >通常</button>
          <button
            className={"rate-btn" + (rate === 0.75 ? " is-on" : "")}
            onClick={() => setRate(0.75)}
          >ゆっくり ×0.75</button>
          <span className="play-count">再生 {played} 回</span>
        </div>
      </div>
    </div>
  );
}

// ============ READING MCQ ============
function ReadingMCQ({ data, onExit }) {
  const [idx, setIdx] = useState(0);
  const [picked, setPicked] = useState(null);
  const [locked, setLocked] = useState(false);
  const [score, setScore] = useState(0);
  const [done, setDone] = useState(false);
  const q = data.readingMCQ[idx];

  function pick(i) {
    if (locked) return;
    setPicked(i); setLocked(true);
    if (i === q.correct) setScore(s => s + 1);
  }
  function next() {
    if (idx + 1 >= data.readingMCQ.length) { setDone(true); return; }
    setIdx(idx + 1); setPicked(null); setLocked(false);
  }
  function restart() { setIdx(0); setPicked(null); setLocked(false); setScore(0); setDone(false); }

  if (done) {
    return (
      <div className="act-wrap">
        <div className="result-card">
          <div className="result-score">{score} / {data.readingMCQ.length}</div>
          <div className="result-label">問正解</div>
          <div className="result-msg">
            {score === data.readingMCQ.length ? "Perfect! 本文の核心をしっかり掴めています。" :
             score >= 3 ? "Good job! もう一度本文を見直すとさらに確実になります。" :
             "Keep going! 本文に戻って、筆者の \"warning\" の意味を確認しよう。"}
          </div>
          <div className="btn-row">
            <Btn onClick={restart} variant="ghost">もう一度</Btn>
            <Btn onClick={_done('reading-mcq', onExit)}>ダッシュボードへ</Btn>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="act-wrap">
      <div className="act-header">
        <div className="act-crumb">Reading · 本文理解</div>
        <ProgressDots total={data.readingMCQ.length} current={idx} />
      </div>
      <div className="passage-box">
        <div className="passage-label">{data.summary ? "Summary" : "Passage"}</div>
        {(data.summary || data.passage).map((p, i) => <p key={i}>{p}</p>)}
      </div>
      <div className="q-card">
        <div className="q-num">Q{idx + 1}</div>
        <div className="q-text">{q.q}</div>
        <div className="choices">
          {q.choices.map((c, i) => {
            let cls = "choice";
            if (locked) {
              if (i === q.correct) cls += " is-correct";
              else if (i === picked) cls += " is-wrong";
              else cls += " is-dim";
            } else if (i === picked) cls += " is-picked";
            return (
              <button key={i} className={cls} onClick={() => pick(i)} disabled={locked}>
                <span className="choice-letter">{String.fromCharCode(65 + i)}</span>
                <span>{c}</span>
              </button>
            );
          })}
        </div>
        {locked && (
          <>
            <Feedback state={picked === q.correct ? "correct" : "wrong"}
              correct={q.choices[q.correct]} explain={q.explain} />
            <div className="btn-row">
              <Btn onClick={next}>{idx + 1 === data.readingMCQ.length ? "結果を見る" : "次の問題"}</Btn>
            </div>
          </>
        )}
      </div>
    </div>
  );
}

// ============ SCANNING ============
function Scanning({ data, onExit }) {
  const [answers, setAnswers] = useState(() => data.scanning.items.map(() => ""));
  const [checked, setChecked] = useState(false);

  const score = answers.reduce((acc, a, i) => acc + (fuzzyMatch(a, data.scanning.items[i].answer) ? 1 : 0), 0);

  return (
    <div className="act-wrap">
      <div className="act-header">
        <div className="act-crumb">Reading · Scanning</div>
      </div>
      <div className="passage-box">
        <div className="passage-label">Passage</div>
        {data.passage.map((p, i) => <p key={i}>{p}</p>)}
      </div>
      <div className="q-card">
        <div className="q-text" style={{marginBottom: 14}}>{data.scanning.instruction}</div>
        <table className="scan-table">
          <thead>
            <tr><th>意味</th><th>英語（本文から探して書く）</th></tr>
          </thead>
          <tbody>
            {data.scanning.items.map((it, i) => {
              const ok = fuzzyMatch(answers[i], it.answer);
              return (
                <tr key={i}>
                  <td>{it.clue}</td>
                  <td>
                    <input
                      className={"scan-input" + (checked ? (ok ? " ok" : " no") : "")}
                      value={answers[i]}
                      onChange={e => setAnswers(a => a.map((x, j) => j === i ? e.target.value : x))}
                      placeholder="英語で記入"
                      disabled={checked}
                    />
                    {checked && !ok && <div className="scan-ans">→ {it.answer}</div>}
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
        <div className="btn-row">
          {!checked ? (
            <Btn onClick={() => setChecked(true)}>採点する</Btn>
          ) : (
            <>
              <div className="inline-score">{score} / {data.scanning.items.length} 正解</div>
              <Btn onClick={() => { setAnswers(data.scanning.items.map(() => "")); setChecked(false); }} variant="ghost">やり直す</Btn>
              <Btn onClick={_done('scanning', onExit)}>ダッシュボードへ</Btn>
            </>
          )}
        </div>
      </div>
    </div>
  );
}

// ============ LISTENING DICTATION ============
function Dictation({ data, onExit }) {
  const [idx, setIdx] = useState(0);
  const [input, setInput] = useState("");
  const [checked, setChecked] = useState(false);
  const [score, setScore] = useState(0);
  const [done, setDone] = useState(false);
  const it = data.listening.dictation.items[idx];
  const ok = fuzzyMatch(input, it.answer);

  function check() {
    setChecked(true);
    if (ok) setScore(s => s + 1);
  }
  function next() {
    if (idx + 1 >= data.listening.dictation.items.length) { setDone(true); return; }
    setIdx(idx + 1); setInput(""); setChecked(false);
  }

  if (done) return (
    <div className="act-wrap"><div className="result-card">
      <div className="result-score">{score} / {data.listening.dictation.items.length}</div>
      <div className="result-label">文正解</div>
      <div className="btn-row"><Btn onClick={_done('dictation', onExit)}>ダッシュボードへ</Btn></div>
    </div></div>
  );

  return (
    <div className="act-wrap">
      <div className="act-header">
        <div className="act-crumb">Listening · Dictation</div>
        <ProgressDots total={data.listening.dictation.items.length} current={idx} />
      </div>
      <div className="q-card">
        <AudioPlayer
          src={it.audio}
          label={it.audioLabel + " — " + (data.listening.dictation.items.length) + "文中 " + (idx + 1) + " 文目"}
        />
        <div className="q-text">{data.listening.dictation.instruction}</div>
        <textarea
          className="dict-input"
          placeholder="聞こえた英文をここに入力"
          value={input}
          onChange={e => setInput(e.target.value)}
          disabled={checked}
          rows={3}
        />
        {checked && (
          <Feedback state={ok ? "correct" : "wrong"} correct={it.answer}
            explain={ok ? "Well heard!" : "スペリング・語順・冠詞にも注意しよう。"} />
        )}
        <div className="btn-row">
          {!checked
            ? <Btn onClick={check} disabled={!input.trim()}>答え合わせ</Btn>
            : <Btn onClick={next}>{idx + 1 === data.listening.dictation.items.length ? "結果を見る" : "次の文"}</Btn>}
        </div>
      </div>
    </div>
  );
}

// ============ LISTENING CLOZE ============
function ListeningCloze({ data, onExit }) {
  const [idx, setIdx] = useState(0);
  const [vals, setVals] = useState(() => data.listening.cloze.script[0].answers.map(() => ""));
  const [checked, setChecked] = useState(false);
  const [done, setDone] = useState(false);
  const [totalOK, setTotalOK] = useState(0);
  const [totalAll, setTotalAll] = useState(0);
  const line = data.listening.cloze.script[idx];

  function check() {
    const got = vals.filter((v, i) => fuzzyMatch(v, line.answers[i])).length;
    setTotalOK(s => s + got);
    setTotalAll(s => s + line.answers.length);
    setChecked(true);
  }
  function next() {
    if (idx + 1 >= data.listening.cloze.script.length) { setDone(true); return; }
    const ni = idx + 1;
    setIdx(ni);
    setVals(data.listening.cloze.script[ni].answers.map(() => ""));
    setChecked(false);
  }

  if (done) return (
    <div className="act-wrap"><div className="result-card">
      <div className="result-score">{totalOK} / {totalAll}</div>
      <div className="result-label">空欄正解</div>
      <div className="btn-row"><Btn onClick={_done('listening-cloze', onExit)}>ダッシュボードへ</Btn></div>
    </div></div>
  );

  return (
    <div className="act-wrap">
      <div className="act-header">
        <div className="act-crumb">Listening · Fill in the Blanks</div>
        <ProgressDots total={data.listening.cloze.script.length} current={idx} />
      </div>
      <div className="q-card">
        <AudioPlayer
          src={line.audio}
          label={"Line " + (idx + 1) + " / " + data.listening.cloze.script.length}
        />
        <div className="cloze-line">
          {line.parts.map((p, i) => (
            <React.Fragment key={i}>
              <span>{p}</span>
              {i < line.answers.length && (
                <input
                  className={"cloze-input" + (checked ? (fuzzyMatch(vals[i], line.answers[i]) ? " ok" : " no") : "")}
                  value={vals[i]}
                  onChange={e => setVals(v => v.map((x, j) => j === i ? e.target.value : x))}
                  disabled={checked}
                  placeholder="___"
                />
              )}
            </React.Fragment>
          ))}
        </div>
        {checked && (
          <div className="cloze-answers">
            <b>正解：</b>
            {line.answers.map((a, i) => (
              <span key={i} className="chip-ans">{a}</span>
            ))}
          </div>
        )}
        <div className="btn-row">
          {!checked ? <Btn onClick={check}>答え合わせ</Btn>
            : <Btn onClick={next}>{idx + 1 === data.listening.cloze.script.length ? "結果を見る" : "次の文"}</Btn>}
        </div>
      </div>
    </div>
  );
}

// ============ VOCAB FLASHCARDS ============
function Flashcards({ data, onExit }) {
  const [idx, setIdx] = useState(0);
  const [flip, setFlip] = useState(false);
  const card = data.vocab[idx];
  const next = () => { setIdx((idx + 1) % data.vocab.length); setFlip(false); };
  const prev = () => { setIdx((idx - 1 + data.vocab.length) % data.vocab.length); setFlip(false); };

  return (
    <div className="act-wrap">
      <div className="act-header">
        <div className="act-crumb">Vocabulary · Flashcards</div>
        <div className="mini-meta">{idx + 1} / {data.vocab.length}</div>
      </div>
      <div className={"flashcard " + (flip ? "is-flip" : "")} onClick={() => setFlip(!flip)}>
        <div className="flashcard-inner">
          <div className="flash-face flash-front">
            <div className="flash-pos">{card.pos}</div>
            <div className="flash-w">{card.w}</div>
            <div className="flash-hint">タップして意味を表示</div>
          </div>
          <div className="flash-face flash-back">
            <div className="flash-jp">{card.jp}</div>
            <div className="flash-ex">ex. {card.ex}</div>
            <div className="flash-hint">タップして戻る</div>
          </div>
        </div>
      </div>
      <div className="btn-row center">
        <Btn onClick={prev} variant="ghost">← 前へ</Btn>
        <Btn onClick={next}>次へ →</Btn>
        <Btn onClick={_done('flashcards', onExit)} variant="ghost">ダッシュボードへ</Btn>
      </div>
    </div>
  );
}

// ============ VOCAB QUIZ ============
function VocabQuiz({ data, onExit }) {
  const [idx, setIdx] = useState(0);
  const [picked, setPicked] = useState(null);
  const [locked, setLocked] = useState(false);
  const [score, setScore] = useState(0);
  const [done, setDone] = useState(false);
  const q = data.vocabQuiz[idx];

  function pick(i) {
    if (locked) return;
    setPicked(i); setLocked(true);
    if (i === q.correct) setScore(s => s + 1);
  }
  function next() {
    if (idx + 1 >= data.vocabQuiz.length) { setDone(true); return; }
    setIdx(idx + 1); setPicked(null); setLocked(false);
  }
  function restart() { setIdx(0); setPicked(null); setLocked(false); setScore(0); setDone(false); }

  if (done) return (
    <div className="act-wrap"><div className="result-card">
      <div className="result-score">{score} / {data.vocabQuiz.length}</div>
      <div className="result-label">問正解</div>
      <div className="btn-row">
        <Btn onClick={restart} variant="ghost">もう一度</Btn>
        <Btn onClick={_done('vocab-quiz', onExit)}>ダッシュボードへ</Btn>
      </div>
    </div></div>
  );

  return (
    <div className="act-wrap">
      <div className="act-header">
        <div className="act-crumb">Vocabulary · Quiz</div>
        <ProgressDots total={data.vocabQuiz.length} current={idx} />
      </div>
      <div className="q-card">
        <div className="vq-prompt">意味として正しいものを選びなさい</div>
        <div className="vq-word">{q.q}</div>
        <div className="choices">
          {q.choices.map((c, i) => {
            let cls = "choice";
            if (locked) {
              if (i === q.correct) cls += " is-correct";
              else if (i === picked) cls += " is-wrong";
              else cls += " is-dim";
            } else if (i === picked) cls += " is-picked";
            return (
              <button key={i} className={cls} onClick={() => pick(i)} disabled={locked}>
                <span className="choice-letter">{String.fromCharCode(65 + i)}</span>
                <span>{c}</span>
              </button>
            );
          })}
        </div>
        {locked && (
          <>
            <Feedback state={picked === q.correct ? "correct" : "wrong"}
              correct={q.choices[q.correct]} />
            <div className="btn-row"><Btn onClick={next}>{idx + 1 === data.vocabQuiz.length ? "結果を見る" : "次"}</Btn></div>
          </>
        )}
      </div>
    </div>
  );
}

// ============ GRAMMAR ============
function Grammar({ data, onExit }) {
  const [phase, setPhase] = useState("learn"); // learn | practice | result
  const [idx, setIdx] = useState(0);
  const [picked, setPicked] = useState(null);
  const [locked, setLocked] = useState(false);
  const [score, setScore] = useState(0);
  const ex = data.grammar.exercises[idx];

  if (phase === "learn") {
    return (
      <div className="act-wrap">
        <div className="act-header"><div className="act-crumb">Grammar · Points</div></div>
        <div className="q-card">
          {data.grammar.points.map((p, i) => (
            <div className="gr-point" key={i}>
              <div className="gr-form">{p.form}</div>
              <div className="gr-mean">{p.meaning}</div>
              <div className="gr-ex">
                {p.examples.map((e, j) => <div key={j}>· {e}</div>)}
              </div>
            </div>
          ))}
          <div className="btn-row"><Btn onClick={() => setPhase("practice")}>練習問題へ →</Btn></div>
        </div>
      </div>
    );
  }

  if (phase === "result") return (
    <div className="act-wrap"><div className="result-card">
      <div className="result-score">{score} / {data.grammar.exercises.length}</div>
      <div className="result-label">問正解</div>
      <div className="btn-row">
        <Btn onClick={() => { setPhase("learn"); setIdx(0); setScore(0); setPicked(null); setLocked(false); }} variant="ghost">復習する</Btn>
        <Btn onClick={_done('grammar', onExit)}>ダッシュボードへ</Btn>
      </div>
    </div></div>
  );

  function pick(i) {
    if (locked) return;
    setPicked(i); setLocked(true);
    if (i === ex.correct) setScore(s => s + 1);
  }
  function next() {
    if (idx + 1 >= data.grammar.exercises.length) { setPhase("result"); return; }
    setIdx(idx + 1); setPicked(null); setLocked(false);
  }

  return (
    <div className="act-wrap">
      <div className="act-header">
        <div className="act-crumb">Grammar · Practice</div>
        <ProgressDots total={data.grammar.exercises.length} current={idx} />
      </div>
      <div className="q-card">
        <div className="q-num">Q{idx + 1}</div>
        <div className="gr-jp">{ex.jp}</div>
        <div className="q-text" style={{fontSize: 13, color:'var(--muted)', marginBottom: 8}}>上の日本語に最も近い英文を選びなさい。</div>
        <div className="choices">
          {ex.choices.map((c, i) => {
            let cls = "choice";
            if (locked) {
              if (i === ex.correct) cls += " is-correct";
              else if (i === picked) cls += " is-wrong";
              else cls += " is-dim";
            } else if (i === picked) cls += " is-picked";
            return (
              <button key={i} className={cls} onClick={() => pick(i)} disabled={locked}>
                <span className="choice-letter">{String.fromCharCode(65 + i)}</span>
                <span>{c}</span>
              </button>
            );
          })}
        </div>
        {locked && (
          <>
            <Feedback state={picked === ex.correct ? "correct" : "wrong"}
              correct={ex.choices[ex.correct]} explain={ex.explain} />
            <div className="btn-row"><Btn onClick={next}>{idx + 1 === data.grammar.exercises.length ? "結果を見る" : "次"}</Btn></div>
          </>
        )}
      </div>
    </div>
  );
}

// ============ SPEAKING (role play) ============
function Speaking({ data, onExit }) {
  const [sIdx, setSIdx] = useState(0);
  const [show, setShow] = useState(false);
  const sc = data.speaking.scenarios[sIdx];

  return (
    <div className="act-wrap">
      <div className="act-header">
        <div className="act-crumb">Speaking · Role Play</div>
      </div>
      <div className="sc-picker">
        {data.speaking.scenarios.map((s, i) => (
          <button key={i}
            className={"sc-btn" + (sIdx === i ? " is-active" : "")}
            onClick={() => { setSIdx(i); setShow(false); }}>
            <span className="sc-num">{i + 1}</span>{s.title}
          </button>
        ))}
      </div>
      <div className="q-card">
        <div className="sc-title">{sc.title}</div>
        <div className="sc-roles">
          <div className="sc-role"><span>あなた</span>{sc.yourRole}</div>
          <div className="sc-role"><span>相手</span>{sc.partnerRole}</div>
        </div>
        <div className="sc-context"><b>場面</b>　{sc.context}</div>
        <div className="sc-instruct">
          <b>Task</b>　ペアで役を決めて、上の場面を英語で演じてみよう。
          話す前に、自分だったらどう伝えるかを頭の中で組み立ててから始めよう。
          <br/>困ったときは <b>Sample Script</b> を開いて参考にしよう。
        </div>
        <button className="reveal-toggle" onClick={() => setShow(s => !s)}>
          {show ? "▼ Sample Script を隠す" : "▶ Sample Script を表示（ヒント）"}
        </button>
        {show && (
          <div className="script">
            {sc.sampleScript.map((ln, i) => (
              <div key={i} className={"script-ln " + (ln.who === "You" ? "you" : "other")}>
                <div className="script-who">{ln.who}</div>
                <div className="script-txt">{ln.line}</div>
              </div>
            ))}
          </div>
        )}
        <div className="btn-row"><Btn onClick={_done('speaking', onExit)}>ダッシュボードへ</Btn></div>
      </div>
    </div>
  );
}

// ============ WRITING ============
function Writing({ data, onExit }) {
  const [pIdx, setPIdx] = useState(0);
  const [text, setText] = useState("");
  const [showSample, setShowSample] = useState(false);
  const p = data.writing.prompts[pIdx];
  const wc = text.trim().split(/\s+/).filter(Boolean).length;

  return (
    <div className="act-wrap">
      <div className="act-header">
        <div className="act-crumb">Writing · Composition</div>
      </div>
      <div className="sc-picker">
        {data.writing.prompts.map((pp, i) => (
          <button key={i}
            className={"sc-btn" + (pIdx === i ? " is-active" : "")}
            onClick={() => { setPIdx(i); setText(""); setShowSample(false); }}>
            <span className="sc-num">{i + 1}</span>{pp.title}
          </button>
        ))}
      </div>
      <div className="q-card">
        <div className="wr-prompt">{p.prompt}</div>
        <div className="wr-hints">
          <div className="wr-hints-label">Hints</div>
          {p.hints.map((h, i) => <div key={i} className="wr-hint">· {h}</div>)}
        </div>
        <textarea
          className="wr-input"
          placeholder="ここに英語で書こう"
          value={text}
          onChange={e => setText(e.target.value)}
          rows={8}
        />
        <div className="wr-meta">Word count: <b>{wc}</b></div>
        <button className="reveal-toggle" onClick={() => setShowSample(s => !s)}>
          {showSample ? "▼ Sample Answer を隠す" : "▶ Sample Answer を表示"}
        </button>
        {showSample && (
          <div className="sample-box">
            <div className="sample-label">Sample Answer</div>
            <div className="sample-body">{p.sample}</div>
          </div>
        )}
        <div className="btn-row"><Btn onClick={_done('writing', onExit)}>ダッシュボードへ</Btn></div>
      </div>
    </div>
  );
}

Object.assign(window, {
  ReadingMCQ, Scanning, Dictation, ListeningCloze,
  Flashcards, VocabQuiz, Grammar, Speaking, Writing,
});
