/* Runner - blocs reparation (cloze/produce) et bloc generique. Extrait de runner.jsx (decoupage 2026-06-12, sans changement de logique). */

function RunnerRepairBlock({ exercise, onDone }) {
  const p = exercise.prompt || {};
  const f = exercise.feedback || {};
  const drill = (p.drill && p.drill.mode) ? p.drill : { mode: "produce", anchor: "" };
  const tags = Array.isArray(exercise.errorTags) ? exercise.errorTags : [];
  const examples = (exercise.expected && Array.isArray(exercise.expected.examples) ? exercise.expected.examples : [])
    .map(ex => typeof ex === "string" ? { kr: ex } : { kr: ex && (ex.kr || ex.text || ex.answer || ""), fr: ex && (ex.fr || ex.en || ex.meaning || "") })
    .filter(ex => ex.kr || ex.fr)
    .slice(0, 2);
  const warning = polishRunnerText(p.warning || f.warning);
  const hint = repairSpecificHint(drill, explanationForTags(tags, warning));
  const [order, setOrder] = useState([]);   // choix mélangés (choose_form)
  const [picked, setPicked] = useState(null);
  const [answer, setAnswer] = useState("");  // produce
  const [checked, setChecked] = useState(null);
  useEffect(() => {
    setPicked(null); setAnswer(""); setChecked(null);
    if ((drill.mode === "choose_form" || drill.mode === "contrast") && Array.isArray(drill.choices)) {
      const arr = drill.choices.slice();
      for (let i = arr.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); const t = arr[i]; arr[i] = arr[j]; arr[j] = t; }
      setOrder(arr);
    } else setOrder([]);
  }, [exercise.id]);

  const Header = (
    <>
      <Eyebrow>Réparation ciblée</Eyebrow>
      <div style={{ fontFamily: "var(--serif)", fontSize: 20, color: "var(--accent-deep)" }}>{polishRunnerText(p.label)}</div>
      {warning && <p className="muted" style={{ fontSize: 14.5, margin: 0 }}>{warning}</p>}
      {p.pattern && <div className="faint" style={{ fontSize: 13 }}>Patron : <span className="kr">{p.pattern}</span></div>}
    </>
  );

  if (drill.mode === "contrast") {
    const answered = picked != null;
    const correct = picked === drill.answer;
    const glosses = drill.glosses || {};
    return (
      <div style={{ display: "grid", gap: 16 }}>
        <div className="card" style={{ padding: 24, display: "grid", gap: 12, borderLeft: "3px solid var(--warn)" }}>
          {Header}
          <div className="eyebrow">Quelle forme pour ce sens ?</div>
          <div style={{ fontFamily: "var(--serif)", fontSize: 22, color: "var(--accent-deep)" }}>{drill.question}</div>
          <div style={{ display: "grid", gap: 8 }}>
            {order.map((c, idx) => {
              let bg = "var(--card)", col = "var(--ink)";
              if (answered && c === drill.answer) { bg = "var(--good-tint)"; col = "var(--good)"; }
              else if (answered && c === picked && !correct) { bg = "var(--warn-tint)"; col = "var(--warn)"; }
              return <button key={idx} onClick={() => picked == null && setPicked(c)} disabled={answered} className="kr" style={{ padding: "12px 15px", borderRadius: "var(--radius-sm)", border: "1px solid var(--rule)", background: bg, color: col, fontSize: 22, textAlign: "center", cursor: answered ? "default" : "pointer" }}>{c}</button>;
            })}
          </div>
          {answered && (
            <div className="fade-up" style={{ display: "grid", gap: 8, padding: "12px 14px", borderRadius: "var(--radius-sm)", background: correct ? "var(--good-tint)" : "var(--warn-tint)" }}>
              <div style={{ fontWeight: 700, color: correct ? "var(--good)" : "var(--warn)" }}>{correct ? "Juste" : "À revoir"}</div>
              <div style={{ display: "grid", gridTemplateColumns: "auto 1fr", gap: "4px 12px", alignItems: "baseline" }}>
                <span className="kr" style={{ fontSize: 18, fontWeight: 700, color: "var(--good)" }}>{drill.answer}</span>
                <span style={{ fontSize: 13.5 }}>{glosses[drill.answer] || drill.question}</span>
                <span className="kr" style={{ fontSize: 18, color: "var(--warn)", textDecoration: "line-through", textDecorationColor: "var(--warn)" }}>{drill.distractor}</span>
                <span className="faint" style={{ fontSize: 13 }}>{glosses[drill.distractor] || "autre sens"}</span>
              </div>
            </div>
          )}
        </div>
        <div style={{ display: "flex", justifyContent: "flex-end", gap: 8 }}>
          {answered && <Btn kind="primary" icon="check" onClick={() => onDone({ correct, answer: picked || "", errorTags: correct ? [] : tags, feedbackShown: true })}>Continuer</Btn>}
        </div>
      </div>
    );
  }

  if (drill.mode === "choose_form") {
    const answered = picked != null;
    const correct = picked === drill.answer;
    const parts = String(drill.cloze || "").split("____");
    const filled = answered ? picked : "____";
    return (
      <div style={{ display: "grid", gap: 16 }}>
        <div className="card" style={{ padding: 24, display: "grid", gap: 12, borderLeft: "3px solid var(--warn)" }}>
          {Header}
          <div className="eyebrow">Complète avec la bonne forme</div>
          <div className="kr" style={{ fontSize: 26, color: "var(--ink)" }}>
            {parts[0]}<span style={{ padding: "0 8px", borderBottom: `2px solid ${answered ? (correct ? "var(--good)" : "var(--warn)") : "var(--accent)"}`, color: answered ? (correct ? "var(--good)" : "var(--warn)") : "var(--accent)", fontWeight: 700 }}>{filled}</span>{parts[1] || ""}
          </div>
          <div style={{ display: "grid", gap: 8 }}>
            {order.map((c, idx) => {
              let bg = "var(--card)", col = "var(--ink)";
              if (answered && c === drill.answer) { bg = "var(--good-tint)"; col = "var(--good)"; }
              else if (answered && c === picked && !correct) { bg = "var(--warn-tint)"; col = "var(--warn)"; }
              return <button key={idx} onClick={() => picked == null && setPicked(c)} disabled={answered} className="kr" style={{ padding: "12px 15px", borderRadius: "var(--radius-sm)", border: "1px solid var(--rule)", background: bg, color: col, fontSize: 20, textAlign: "center", cursor: answered ? "default" : "pointer" }}>{c}</button>;
            })}
          </div>
          {answered && (
            <div className="fade-up" style={{ display: "grid", gap: 6, padding: "12px 14px", borderRadius: "var(--radius-sm)", background: correct ? "var(--good-tint)" : "var(--warn-tint)" }}>
              <div style={{ fontWeight: 700, color: correct ? "var(--good)" : "var(--warn)" }}>{correct ? "Juste" : "À revoir"}</div>
              <div>Forme correcte : <span className="kr" style={{ fontSize: 18, fontWeight: 700 }}>{drill.full}</span></div>
              <div className="faint" style={{ fontSize: 13 }}>{hint}</div>
            </div>
          )}
        </div>
        <div style={{ display: "flex", justifyContent: "flex-end", gap: 8 }}>
          {answered && <Btn kind="primary" icon="check" onClick={() => onDone({ correct, answer: picked || "", errorTags: correct ? [] : tags, feedbackShown: true })}>Continuer</Btn>}
        </div>
      </div>
    );
  }

  // Mode produire : micro-phrase qui réutilise l'ancre du patron (contrôle objectif).
  const reuse = answer.trim();
  const need = (drill.anchor || "").trim();
  const ok = !!checked && checked.ok;
  const check = () => {
    const passes = need ? (reuse.indexOf(need) >= 0 && reuse.length > need.length) : reuse.length >= 2;
    setChecked({ ok: passes, reason: passes ? "" : (need ? `Réutilise « ${need} » dans une phrase à toi.` : "Écris une micro-phrase complète.") });
  };
  return (
    <div style={{ display: "grid", gap: 16 }}>
      <div className="card" style={{ padding: 24, display: "grid", gap: 10, borderLeft: "3px solid var(--warn)" }}>
        {Header}
        {examples.length > 0 && (
          <div style={{ display: "grid", gap: 6 }}>
            <div className="eyebrow">Modèles</div>
            {examples.map((ex, i) => (
              <div key={i} style={{ display: "grid", gap: 3, padding: "9px 11px", borderRadius: "var(--radius-sm)", background: "var(--card-2)", border: "1px solid var(--rule)" }}>
                {ex.kr && <span className="kr" style={{ fontSize: 17 }}>{ex.kr}</span>}
                {(ex.fr || ex.en) && <span className="faint" style={{ fontSize: 12.5 }}>{ex.fr || ex.en}</span>}
              </div>
            ))}
          </div>
        )}
        <div className="eyebrow">{need ? <>Écris une micro-phrase avec <span className="kr">{need}</span></> : "Écris une micro-phrase qui applique le patron"}</div>
        <textarea value={answer} onChange={ev => { setAnswer(ev.target.value); setChecked(null); }} rows={2} placeholder="Ta micro-phrase en coréen…" className="kr" lang="ko" autoCapitalize="off" autoCorrect="off" spellCheck={false}
          style={{ width: "100%", padding: "11px 13px", borderRadius: "var(--radius-sm)", border: "1px solid var(--rule)", background: "var(--card-2)", color: "var(--ink)", fontSize: 18, resize: "vertical" }} />
        <KoreanKeyboard value={answer} onChange={(next) => { setAnswer(next); setChecked(null); }} compact />
        {checked && (
          <div className="fade-up" style={{ display: "grid", gap: 4, padding: "10px 12px", borderRadius: "var(--radius-sm)", background: ok ? "var(--good-tint)" : "var(--warn-tint)", color: ok ? "var(--good)" : "var(--warn)", fontSize: 13.5 }}>
            <span style={{ fontWeight: 700 }}>{ok ? "Patron réutilisé — bien" : "Pas encore"}</span>
            {!ok && <span className="faint" style={{ fontSize: 12.5 }}>{checked.reason} À retenir : {hint}</span>}
          </div>
        )}
      </div>
      <div style={{ display: "flex", justifyContent: "flex-end", gap: 8, flexWrap: "wrap" }}>
        {!ok && <Btn kind="secondary" icon="eye" disabled={!reuse} onClick={check}>Vérifier</Btn>}
        {checked && !ok && <Btn kind="ghost" size="sm" onClick={() => onDone({ correct: false, answer: reuse, errorTags: tags, feedbackShown: true })}>Continuer (fragile)</Btn>}
        {ok && <Btn kind="primary" icon="check" onClick={() => onDone({ correct: true, answer: reuse, feedbackShown: true })}>Continuer</Btn>}
      </div>
    </div>
  );
}

function RunnerGenericBlock({ exercise, onDone }) {
  return (
    <div style={{ display: "grid", gap: 16 }}>
      <div className="card" style={{ padding: 24 }}>
        <Eyebrow>{(exercise.type || "exercice").replace(/_/g, " ")}</Eyebrow>
        <p className="muted" style={{ fontSize: 14.5, margin: "10px 0 0" }}>Bloc sans surface dédiée pour l'instant — marquez-le fait pour continuer la séance.</p>
      </div>
      <div style={{ display: "flex", justifyContent: "flex-end" }}>
        <Btn kind="primary" icon="check" onClick={() => onDone({ correct: true })}>Fait · continuer</Btn>
      </div>
    </div>
  );
}

