/* Test de transfert différé — PEDAGOGIE §8/P3 : « ça coule » n'est pas « c'est
   acquis ». On reprend des cartes STABLES dans un habillage JAMAIS montré
   (cloze dans une phrase porteuse secondaire). Réussir ne touche pas FSRS ;
   échouer renvoie la carte plus tôt (early lapse borné) et se journalise. */

function transferLoadDeps() {
  return Promise.all([
    window.LangData.loadChunkIndex(),
    window.LangData.loadVocabFreq(),
  ]).then(([chunkIndex, vocab]) => {
    const vocabById = Object.create(null);
    (vocab.items || []).forEach(it => { if (it.id) vocabById[it.id] = it; });
    return { chunkIndex, vocabById };
  });
}

function transferCandidates(deps) {
  if (!window.LangTransfer || !window.LangStore || !window.LangStore.cards) return [];
  return window.LangTransfer.selectCandidates({
    cards: window.LangStore.cards.all(),
    chunkIndex: deps.chunkIndex,
    vocabById: deps.vocabById,
    now: Date.now(),
  });
}

function TransferCheck() {
  const [deps, setDeps] = useState(null);
  const [error, setError] = useState("");
  const [items, setItems] = useState(null);     // null = pas encore évalué
  const [run, setRun] = useState(null);         // {idx, correct, total, results}
  const [answer, setAnswer] = useState("");
  const [checked, setChecked] = useState(null); // {correct, contrast, comeBack}
  const sessionRef = useRef(null);

  useEffect(() => {
    let alive = true;
    if (!window.LangData || !window.LangTransfer) { setError("Moteur de transfert indisponible."); return () => { alive = false; }; }
    transferLoadDeps()
      .then(d => { if (alive) { setDeps(d); setItems(transferCandidates(d)); } })
      .catch(() => { if (alive) setError("Données de transfert indisponibles."); });
    return () => { alive = false; if (window.LangAudio) window.LangAudio.stop(); };
  }, []);

  const start = () => {
    if (!items || !items.length) return;
    if (window.LangSessionLog && window.LangStore) {
      sessionRef.current = window.LangSessionLog.startSession({
        profile: window.LangStore.profile,
        intention: "transfert",
        charge: "mesure",
        plannedMinutes: Math.max(2, Math.round(items.length * 0.7)),
      });
    }
    setRun({ idx: 0, correct: 0, total: 0, startedAt: Date.now() });
    setAnswer("");
    setChecked(null);
  };

  const finishRun = (finalRun) => {
    if (sessionRef.current && window.LangSessionLog && window.LangStore) {
      window.LangSessionLog.finishSession(sessionRef.current, window.LangStore, Date.now());
      sessionRef.current = null;
    }
    setRun(finalRun);
  };

  if (error) return null; // le Pilotage reste lisible sans ce panneau
  if (!deps || items === null) return null;

  const item = run && run.idx < items.length ? items[run.idx] : null;

  /* --- pas encore lancé / rien à tester --- */
  if (!run) {
    return (
      <Panel title="Test de transfert" hint={items.length ? `${items.length} item${items.length > 1 ? "s" : ""} prêt${items.length > 1 ? "s" : ""}` : "hebdomadaire"}>
        {items.length === 0 ? (
          <p className="faint" style={{ fontSize: 13, margin: 0 }}>
            Rien à tester : il faut des cartes stables (≥ 7 j), pas dues bientôt et pas
            testées cette semaine. Reviens quand des cartes auront mûri.
          </p>
        ) : (
          <div style={{ display: "grid", gap: 10 }}>
            <p className="faint" style={{ fontSize: 13, margin: 0 }}>
              Tes items les plus stables, repris dans une phrase jamais montrée.
              Réussir ne change rien ; échouer fait revenir la carte plus tôt.
            </p>
            <Btn kind="primary" size="sm" icon="play" onClick={start}>Tester · {items.length} items</Btn>
          </div>
        )}
      </Panel>
    );
  }

  /* --- bilan --- */
  if (!item) {
    const pct = run.total ? Math.round(100 * run.correct / run.total) : 0;
    return (
      <Panel title="Test de transfert" hint="terminé">
        <div style={{ display: "flex", alignItems: "baseline", gap: 10 }}>
          <span style={{ fontFamily: "var(--serif)", fontSize: 34, color: pct >= 80 ? "var(--good)" : "var(--ochre)" }}>{pct}%</span>
          <span className="faint" style={{ fontSize: 13 }}>{run.correct}/{run.total} transférés</span>
        </div>
        <p className="faint" style={{ fontSize: 12.5, margin: "8px 0 0" }}>
          {pct >= 80
            ? "Le savoir sort de son habillage d'apprentissage — c'est de l'acquis réel."
            : "Les items ratés paraissaient stables mais ne l'étaient qu'en contexte connu : ils reviennent plus tôt en révision."}
        </p>
      </Panel>
    );
  }

  /* --- question courante --- */
  const check = () => {
    const res = window.LangTransfer.grade(window.LangValidate, item, answer);
    const correct = !!(res && res.correct);
    let comeBack = false;
    const store = window.LangStore;
    if (store && store.cards) {
      const prev = store.cards.state(item.cardId);
      let card = prev;
      if (!correct && window.LangPracticeLots) {
        const bounded = window.LangPracticeLots.boundedSrsReview({
          itemId: item.cardId, rating: "rate", prev, now: Date.now(),
          scheduler: window.FSRS,
          retention: (store.settings && store.settings.get().retention) || 0.9,
          errorTags: ["contexte"],
        });
        if (bounded.card) { card = bounded.card; comeBack = true; }
      }
      store.cards.setState(item.cardId, window.LangTransfer.markTested(card || prev || {}, Date.now()));
    }
    if (sessionRef.current && window.LangSessionLog) {
      window.LangSessionLog.logResult(sessionRef.current, {
        exerciseId: `transfer_${item.cardId}`,
        itemId: item.cardId,
        kind: "transfer_check",
        strand: "study",
        startedAt: run.startedAt,
        finishedAt: Date.now(),
        answer,
        correct,
        errorTags: correct ? [] : ["contexte"],
        feedbackShown: true,
      });
    }
    const contrast = correct ? null : window.LangValidate.contrast(item.surface, answer);
    setChecked({ correct, contrast, comeBack });
    if (window.LangSounds) (correct ? window.LangSounds.correct : window.LangSounds.wrong)();
  };

  const next = () => {
    const updated = { ...run, idx: run.idx + 1, total: run.total + 1, correct: run.correct + (checked && checked.correct ? 1 : 0), startedAt: Date.now() };
    setAnswer("");
    setChecked(null);
    if (updated.idx >= items.length) finishRun(updated);
    else setRun(updated);
  };

  return (
    <Panel title="Test de transfert" hint={`${run.idx + 1}/${items.length}`}>
      <div style={{ display: "grid", gap: 10 }}>
        <div className="kr" style={{ fontSize: 19, lineHeight: 1.6 }}>{item.clozeKr}</div>
        {item.sentenceFr && <div className="faint" style={{ fontSize: 12.5 }}>{item.sentenceFr}</div>}
        <div className="faint" style={{ fontSize: 12 }}>Indice : {(item.fr || "").split(/[;,]/)[0].trim()}</div>
        <input value={answer} onChange={ev => { setAnswer(ev.target.value); setChecked(null); }} className="kr" lang="ko"
          autoCapitalize="off" autoCorrect="off" spellCheck={false} placeholder="Le mot manquant…"
          style={{ padding: "9px 11px", borderRadius: "var(--radius-sm)", border: "1px solid var(--rule)", background: "var(--card-2)", color: "var(--ink)", fontSize: 17 }} />
        {checked && (
          <div className="fade-up" style={{ display: "grid", gap: 6, padding: "10px 12px", borderRadius: "var(--radius-sm)", background: checked.correct ? "var(--good-tint)" : "var(--warn-tint)" }}>
            <div style={{ fontWeight: 700, color: checked.correct ? "var(--good)" : "var(--warn)" }}>
              {checked.correct ? "Transféré." : `C'était « ${item.surface} » (${item.kr}).`}
            </div>
            <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }}>
              <Speakable text={item.sentenceKr} as="span" gloss={item.sentenceFr} className="kr" style={{ fontSize: 15 }}>{item.sentenceKr}</Speakable>
            </div>
            {checked.comeBack && <span className="faint" style={{ fontSize: 12 }}>Cette carte paraissait stable : elle revient plus tôt en révision.</span>}
          </div>
        )}
        <div style={{ display: "flex", justifyContent: "flex-end", gap: 8 }}>
          {!checked && <Btn kind="primary" size="sm" icon="check" disabled={!answer.trim()} onClick={check}>Vérifier</Btn>}
          {checked && <Btn kind="primary" size="sm" icon="chevronR" onClick={next}>{run.idx + 1 >= items.length ? "Terminer" : "Suivant"}</Btn>}
        </div>
      </div>
    </Panel>
  );
}

Object.assign(window, { TransferCheck });
