// The quiz engine every quiz activity shares (Space and the other explorers,
// Math Lab): pick a quiz, play it, see the result, fix the misses.
//
//   <QuizFlow activitySlug="space-explorer" theme="space" onBack={...} />
//
// Question types (quizzes.type): multiple_choice, true_false, comparison,
// riddle (all "tap an option") and numeric (type the number on a keypad, for
// Math Lab, where four options are too easy to guess).

const QUIZ_TYPE_LABEL = {
  multiple_choice: 'Pick the answer',
  true_false: 'True or false?',
  comparison: 'Which one?',
  riddle: 'Riddles',
  matching: 'Match it',
  numeric: 'Type the number'
};
const QUIZ_TYPE_ICON = { multiple_choice: '🔍', comparison: '⚖️', true_false: '✅', riddle: '🤔', numeric: '🔢', matching: '🧩' };
const DIFFICULTY_LABEL = { easy: 'Easy', medium: 'Medium', hard: 'Hard' };

// Same forgiveness as the server's sameAnswer(): case, spaces, commas in numbers.
function sameAnswerClient(given, correct) {
  if (given === undefined || given === null) return false;
  const a = String(given).trim().toLowerCase();
  const b = String(correct).trim().toLowerCase();
  if (a === b) return true;
  const na = Number(a.replace(/,/g, '')), nb = Number(b.replace(/,/g, ''));
  return a !== '' && b !== '' && Number.isFinite(na) && Number.isFinite(nb) && na === nb;
}

function NumericPad({ value, onChange, onSubmit, disabled, dark }) {
  const press = d => { if (!disabled && value.length < 5) onChange(value + d); };
  const back = () => { if (!disabled) onChange(value.slice(0, -1)); };
  return (
    <div className={`numpad ${dark ? 'dark' : ''}`}>
      <div className="numpad-display" aria-live="polite">{value || <span className="numpad-placeholder">?</span>}</div>
      <div className="numpad-keys">
        {['1','2','3','4','5','6','7','8','9'].map(d => (
          <button key={d} className="numpad-key" onClick={() => press(d)} disabled={disabled}>{d}</button>
        ))}
        <button className="numpad-key numpad-back" onClick={back} disabled={disabled} aria-label="Delete">⌫</button>
        <button className="numpad-key" onClick={() => press('0')} disabled={disabled}>0</button>
        <button className="numpad-key numpad-go" onClick={onSubmit} disabled={disabled || !value} aria-label="Check my answer">✓</button>
      </div>
    </div>
  );
}

// quizFilter(quiz) narrows the list (Math Lab shows one strategy's quizzes);
// endExtra(result) adds something to the result screen (Math Lab's dragon gift).
function QuizFlow({ activitySlug, theme = 'craft', onBack, backLabel = 'Back', heading = 'Quiz Time!', intro = null,
                    onPlayed, quizFilter = null, endExtra = null }) {
  const dark = theme === 'space';
  const [view, setView] = useState('select'); // select | play | end
  const [quizzes, setQuizzes] = useState(null);
  const [loadError, setLoadError] = useState(null);
  const [quiz, setQuiz] = useState(null);
  const [questions, setQuestions] = useState([]);
  const [idx, setIdx] = useState(0);
  const [answers, setAnswers] = useState({});
  const [feedback, setFeedback] = useState(null); // { correct, answer }
  const [typed, setTyped] = useState('');
  const [showHint, setShowHint] = useState(false);
  const [retry, setRetry] = useState(false);
  const [result, setResult] = useState(null);
  const [badges, setBadges] = useState(null);
  const [confetti, setConfetti] = useState(false);
  const [busy, setBusy] = useState(false);

  const loadQuizzes = useCallback(async () => {
    setLoadError(null);
    const data = await api(`/api/activities/${activitySlug}`);
    if (!data || data.error) { setLoadError(data ? data.error : 'offline'); return; }
    setQuizzes(data.quizzes || []);
  }, [activitySlug]);
  useEffect(() => { loadQuizzes(); }, [loadQuizzes]);

  const burst = ms => { setConfetti(true); setTimeout(() => setConfetti(false), ms); };

  const begin = async (q, asRetry) => {
    if (busy) return;
    setBusy(true);
    const data = await api(asRetry ? `/api/quizzes/${q.id}/retry-missed` : `/api/quizzes/${q.id}`);
    setBusy(false);
    if (!data || data.error || !data.questions || !data.questions.length) return;
    setQuiz(q);
    setRetry(!!asRetry);
    setQuestions(data.questions);
    setIdx(0);
    setAnswers({});
    setFeedback(null);
    setTyped('');
    setShowHint(false);
    setResult(null);
    setView('play');
    window.scrollTo(0, 0);
  };

  const answer = (value) => {
    if (feedback) return;
    const q = questions[idx];
    const correct = sameAnswerClient(value, q.correct_answer);
    setAnswers(prev => ({ ...prev, [q.id]: value }));
    setFeedback({ correct, answer: value });
    if (correct) burst(1500);
  };

  const submit = async (finalAnswers) => {
    setBusy(true);
    const data = await api(`/api/quizzes/${quiz.id}/submit`, {
      method: 'POST', body: { answers: finalAnswers, mode: retry ? 'retry' : undefined }
    });
    setBusy(false);
    if (!data || data.error) { setResult({ error: true }); setView('end'); return; }
    setResult(data);
    setView('end');
    burst(3000);
    if (data.badgesEarned && data.badgesEarned.length) setTimeout(() => setBadges(data.badgesEarned), 900);
    onPlayed && onPlayed(data);
    loadQuizzes();
  };

  const next = () => {
    if (idx < questions.length - 1) {
      setIdx(i => i + 1);
      setFeedback(null);
      setTyped('');
      setShowHint(false);
      window.scrollTo(0, 0);
    } else {
      submit(answers);
    }
  };

  // ─── PICK A QUIZ ──────────
  const renderSelect = () => {
    if (loadError) return <OopsCard message="The quizzes could not load." onRetry={loadQuizzes} />;
    if (!quizzes) return <div className="quiz-loading">Loading quizzes…</div>;
    const visible = quizFilter ? quizzes.filter(quizFilter) : quizzes;
    if (!visible.length) return <div className="quiz-loading">No quizzes here yet. Check back soon!</div>;
    const groups = ['easy', 'medium', 'hard'].map(d => [d, visible.filter(q => (q.difficulty || 'easy') === d)]).filter(([, l]) => l.length);
    return (
      <div className="quiz-selection">
        <h2>{heading}</h2>
        {intro}
        {groups.map(([diff, list]) => (
          <div key={diff} className="quiz-group">
            {groups.length > 1 && <h3 className={`quiz-group-title diff-${diff}`}>{DIFFICULTY_LABEL[diff]}{diff === 'hard' ? ' 🔥' : ''}</h3>}
            {list.map(q => {
              const p = q.userProgress;
              return (
                <div key={q.id} className="quiz-card-wrap">
                  <button className="quiz-card" onClick={() => begin(q, false)} disabled={busy}>
                    <div className="quiz-icon">{QUIZ_TYPE_ICON[q.type] || '❓'}</div>
                    <div className="quiz-info">
                      <div className="quiz-title">{q.title}</div>
                      <div className="quiz-type">{QUIZ_TYPE_LABEL[q.type] || ''}</div>
                      {p
                        ? <div className="quiz-progress"><Stars score={p.score} total={p.total} /> Best {p.score}/{p.total}</div>
                        : <div className="quiz-progress quiz-new">New!</div>}
                    </div>
                    <div className="quiz-go">▶</div>
                  </button>
                  {p && p.missedCount > 0 && (
                    <button className="fix-misses-btn" onClick={() => begin(q, true)} disabled={busy}>
                      🔁 Fix my misses ({p.missedCount})
                    </button>
                  )}
                </div>
              );
            })}
          </div>
        ))}
      </div>
    );
  };

  // ─── PLAY ─────────────────
  const renderPlay = () => {
    const q = questions[idx];
    if (!q) return null;
    const numeric = quiz.type === 'numeric';
    const options = q.options || [];
    const right = Object.entries(answers).filter(([id, a]) => {
      const qq = questions.find(x => String(x.id) === String(id));
      return qq && sameAnswerClient(a, qq.correct_answer);
    }).length;
    return (
      <div className="quiz-player">
        <div className="quiz-top">
          <button className="quiz-quit" onClick={() => setView('select')} aria-label="Stop this quiz">✕</button>
          <div className="quiz-score-bar">
            {retry ? 'Fixing misses' : quiz.title}
            <span className="quiz-count">Question {idx + 1} of {questions.length} · ✓ {right}</span>
          </div>
        </div>
        <div className="quiz-progress-bar">
          <div className="quiz-progress-fill" style={{ width: ((idx + (feedback ? 1 : 0)) / questions.length * 100) + '%' }} />
        </div>
        <div className="question-card">
          <div className={`question-text ${numeric && /^\d+ × \d+ = \?$/.test(q.text) ? 'sum' : ''}`}>{q.text}</div>
          <SpeakButton voiceKey={q.qkey ? `q.${q.qkey}` : null} dark={dark} />
          {numeric ? (
            <NumericPad value={feedback ? String(feedback.answer) : typed} onChange={setTyped}
              onSubmit={() => answer(typed)} disabled={!!feedback} dark={dark} />
          ) : (
            <div className={`answer-options ${options.length === 2 ? 'two' : ''}`}>
              {options.map((opt, i) => {
                let cls = 'answer-btn';
                if (feedback) {
                  if (sameAnswerClient(opt, q.correct_answer)) cls += ' correct';
                  else if (opt === feedback.answer) cls += ' wrong';
                  else cls += ' dim';
                }
                return <button key={i} className={cls} onClick={() => answer(opt)} disabled={!!feedback}>{opt}</button>;
              })}
            </div>
          )}
          {feedback && (
            <div className={`feedback-box ${feedback.correct ? 'yes' : 'no'}`}>
              <div className="feedback-head">
                {feedback.correct ? 'Yes! You got it! 🎉' : <>Not quite. The answer is <strong>{q.correct_answer}</strong>.</>}
              </div>
              {q.explanation && <div className="feedback-why">{q.explanation}</div>}
              <button className="btn-next" onClick={next} disabled={busy} autoFocus>
                {idx < questions.length - 1 ? 'Next question →' : (busy ? 'Adding it up…' : 'See my score →')}
              </button>
            </div>
          )}
        </div>
        {q.hint && !feedback && (
          showHint
            ? <div className="hint-box">💡 {q.hint}</div>
            : <button className="hint-btn" onClick={() => setShowHint(true)}>💡 Need a hint?</button>
        )}
      </div>
    );
  };

  // ─── RESULT ───────────────
  const renderEnd = () => {
    if (!result) return null;
    if (result.error) return <OopsCard message="Your answers didn't save. Let's try that quiz again." onRetry={() => begin(quiz, retry)} />;
    const pct = Math.round((result.score / result.total) * 100);
    let message;
    if (retry) message = result.total === 1 ? (result.score ? 'You fixed it! Brilliant!' : 'Almost! Have another go.')
      : result.score === result.total ? `You fixed all ${result.total}! Brilliant!` : `You fixed ${result.score} of ${result.total}. Keep going!`;
    else if (pct === 100) message = 'PERFECT SCORE! You are amazing!';
    else if (pct >= 80) message = 'Great job! You really know this!';
    else if (pct >= 50) message = 'Nice work! Every try makes your brain stronger.';
    else message = 'Good try! Fix your misses and you’ll have it.';
    const missedLeft = result.progress ? result.progress.missedCount : result.missed.length;
    return (
      <div className="quiz-end">
        <Hoot pose={pct === 100 ? 'cheer' : pct >= 50 ? 'hello' : 'think'} size={120} />
        <h2>{retry ? 'Misses fixed!' : 'Quiz complete!'}</h2>
        <div className="score-display">{result.score} / {result.total}</div>
        {!retry && <Stars score={result.score} total={result.total} size="2rem" />}
        <div className="message">{message}</div>
        {endExtra && endExtra(result)}
        <div className="quiz-end-buttons">
          {missedLeft > 0 && (
            <button className="btn-green" onClick={() => begin(quiz, true)} disabled={busy}>🔁 Fix my misses ({missedLeft})</button>
          )}
          <button className="btn-gold" onClick={() => begin(quiz, false)} disabled={busy}>Play this quiz again</button>
          <button className="btn-space" onClick={() => setView('select')}>Pick another quiz</button>
          <button className="btn-space" onClick={onBack}>{backLabel}</button>
        </div>
      </div>
    );
  };

  return (
    <div className={`quiz-flow quiz-theme-${theme}`}>
      {view === 'select' && (
        <button className="back-btn inline" onClick={onBack}>← {backLabel}</button>
      )}
      {view === 'select' && renderSelect()}
      {view === 'play' && renderPlay()}
      {view === 'end' && renderEnd()}
      {confetti && <Confetti />}
      <BadgeQueue badges={badges} onDone={() => setBadges(null)} />
    </div>
  );
}
