/* global React, window */
// Practice Lab — top-level container component.
//
// Renders:
//   - difficulty selector pills
//   - exercise picker tabs (interval / chord / note / key-sig / scale / mixed)
//   - "Enable sound" splash if AudioContext is not yet running
//   - the currently selected exercise component
//   - session score + streak HUD
//   - lifetime stats footer (admin-only data, but the UI mounts inside
//     the admin tab so this is fine)
//   - floating <FeedbackWidget /> bottom-right
//
// Exposed on window as both PracticeLab.ui.PracticeLab and the bare
// `PracticeLab` symbol so admin-dashboard.jsx can mount it with
// <window.PracticeLab.ui.PracticeLab /> (it does not collide with the
// PracticeLab namespace object because React treats only components
// referenced through a fully-qualified path).

(function () {
  'use strict';
  window.PracticeLab = window.PracticeLab || {};
  window.PracticeLab.ui = window.PracticeLab.ui || {};

  const EXERCISES = [
    { id: 'mixed',         label: 'Mixed' },
    { id: 'interval',      label: 'Interval' },
    { id: 'chord',         label: 'Chord' },
    { id: 'note_staff',    label: 'Note on staff' },
    { id: 'key_signature', label: 'Key signature' },
    { id: 'scale',         label: 'Scale' },
  ];

  const DIFFICULTIES = [
    { id: 'beginner',     label: 'Beginner' },
    { id: 'intermediate', label: 'Intermediate' },
    { id: 'advanced',     label: 'Advanced' },
  ];

  // The 5 real exercise ids that we rotate through in 'mixed' mode.
  const MIXED_POOL = ['interval', 'chord', 'note_staff', 'key_signature', 'scale'];

  function pickNextExercise(currentExercise, lastInMixed) {
    if (currentExercise !== 'mixed') return currentExercise;
    // Rotate so we don't repeat the same exercise twice in a row.
    const pool = MIXED_POOL.filter(function (id) { return id !== lastInMixed; });
    return pool[Math.floor(Math.random() * pool.length)];
  }

  const Pill = function (props) {
    const active = !!props.active;
    return (
      <button
        onClick={props.onClick}
        style={{
          padding: '8px 16px',
          borderRadius: 999,
          border: '1px solid ' + (active ? 'oklch(35% 0.16 265)' : 'oklch(88% 0.02 265)'),
          background: active ? 'oklch(35% 0.16 265)' : '#fff',
          color: active ? '#fff' : 'oklch(28% 0.05 265)',
          fontSize: 13,
          fontWeight: 600,
          cursor: 'pointer',
          fontFamily: "'Plus Jakarta Sans', sans-serif",
          transition: 'all 0.14s',
          whiteSpace: 'nowrap',
        }}
      >{props.children}</button>
    );
  };

  const StatTile = function (props) {
    return (
      <div style={{
        flex: 1,
        minWidth: 110,
        background: '#fff',
        border: '1px solid oklch(92% 0.012 265)',
        borderRadius: 12,
        padding: '14px 18px',
      }}>
        <div style={{ fontSize: 11, color: 'oklch(55% 0.04 265)', fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase', marginBottom: 6 }}>{props.label}</div>
        <div style={{ fontSize: 22, fontWeight: 700, color: 'oklch(18% 0.03 265)', lineHeight: 1.1 }}>{props.value}</div>
        {props.sub && <div style={{ fontSize: 11, color: 'oklch(55% 0.04 265)', marginTop: 4 }}>{props.sub}</div>}
      </div>
    );
  };

  const EnableSoundSplash = function (props) {
    return (
      <div style={{
        background: 'oklch(96% 0.02 80)',
        border: '1px solid oklch(85% 0.07 80)',
        borderRadius: 12,
        padding: '18px 20px',
        marginBottom: 18,
        display: 'flex',
        alignItems: 'center',
        gap: 14,
        flexWrap: 'wrap',
      }}>
        <svg aria-hidden="true" width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="oklch(45% 0.13 80)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
          <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"/>
          <path d="M15.54 8.46a5 5 0 0 1 0 7.07"/>
          <path d="M19.07 4.93a10 10 0 0 1 0 14.14"/>
        </svg>
        <div style={{ flex: 1, minWidth: 200 }}>
          <div style={{ fontSize: 14, fontWeight: 700, color: 'oklch(22% 0.06 265)', marginBottom: 3 }}>Enable sound</div>
          <div style={{ fontSize: 12.5, color: 'oklch(40% 0.04 265)' }}>Browsers require a click before playing audio. One tap and we’re set.</div>
        </div>
        <button
          onClick={props.onEnable}
          style={{
            padding: '10px 18px',
            borderRadius: 10,
            border: 'none',
            background: 'oklch(35% 0.16 265)',
            color: '#fff',
            fontSize: 13,
            fontWeight: 700,
            cursor: 'pointer',
            fontFamily: "'Plus Jakarta Sans', sans-serif",
          }}
        >Enable sound</button>
      </div>
    );
  };

  const MODES = [
    { id: 'curriculum', label: 'Curriculum' },
    { id: 'free',       label: 'Free practice' },
  ];

  const PracticeLab = function () {
    const [mode, setMode] = React.useState('curriculum');
    const [difficulty, setDifficulty] = React.useState('beginner');
    const [exercise, setExercise] = React.useState('mixed');
    const [activeExercise, setActiveExercise] = React.useState(null);
    const [audioReady, setAudioReady] = React.useState(false);

    // Session state (resets when difficulty / exercise changes by user)
    const [sessionScore, setSessionScore] = React.useState({ correct: 0, total: 0 });
    const [streak, setStreak] = React.useState(0);

    // Lifetime stats fetched on mount and refreshed after each attempt.
    const [stats, setStats] = React.useState({ totalAttempts: 0, accuracy: 0, bestStreak: 0 });

    // Last rendered prompt/answer for feedback widget context.
    const lastContext = React.useRef(null);

    // Round counter forces child remount when "Next" is pressed.
    const [roundKey, setRoundKey] = React.useState(0);

    // Decide which exercise to actually render (handles 'mixed' rotation).
    React.useEffect(function () {
      setActiveExercise(function (prev) {
        return pickNextExercise(exercise, prev);
      });
    }, [exercise, roundKey]);

    // Refresh audio readiness flag periodically (cheap).
    React.useEffect(function () {
      const id = setInterval(function () {
        try { setAudioReady(window.PracticeLab.audio.isReady()); } catch (e) {}
      }, 500);
      return function () { clearInterval(id); };
    }, []);

    // Load lifetime stats on mount and after each attempt.
    const refreshStats = React.useCallback(async function () {
      try {
        const s = await window.PracticeLab.db.getLifetimeStats();
        setStats(s);
      } catch (e) { /* ignore — admin-only data */ }
    }, []);

    React.useEffect(function () { refreshStats(); }, [refreshStats]);

    const enableSound = React.useCallback(async function () {
      try {
        await window.PracticeLab.audio.resumeContext();
      } catch (e) {}
      try { setAudioReady(window.PracticeLab.audio.isReady()); } catch (e) {}
    }, []);

    const handleAttempt = React.useCallback(async function (attempt) {
      // attempt: { exerciseType, difficulty, prompt, userAnswer, correctAnswer, wasCorrect }
      lastContext.current = attempt;
      setSessionScore(function (prev) {
        return {
          correct: prev.correct + (attempt.wasCorrect ? 1 : 0),
          total: prev.total + 1,
        };
      });
      setStreak(function (prev) { return attempt.wasCorrect ? prev + 1 : 0; });
      try { await window.PracticeLab.db.recordAttempt(attempt); } catch (e) {}
      refreshStats();
    }, [refreshStats]);

    const handleNext = React.useCallback(function () {
      setRoundKey(function (k) { return k + 1; });
    }, []);

    const handlePickDifficulty = React.useCallback(function (d) {
      setDifficulty(d);
      setSessionScore({ correct: 0, total: 0 });
      setStreak(0);
      setRoundKey(function (k) { return k + 1; });
    }, []);

    const handlePickExercise = React.useCallback(function (e) {
      setExercise(e);
      setSessionScore({ correct: 0, total: 0 });
      setStreak(0);
      setRoundKey(function (k) { return k + 1; });
    }, []);

    const ExerciseComponent = (function () {
      switch (activeExercise) {
        case 'interval':       return window.PracticeLab.ui.ExerciseInterval;
        case 'chord':          return window.PracticeLab.ui.ExerciseChord;
        case 'note_staff':     return window.PracticeLab.ui.ExerciseNoteStaff;
        case 'key_signature':  return window.PracticeLab.ui.ExerciseKeySignature;
        case 'scale':          return window.PracticeLab.ui.ExerciseScale;
        default:               return null;
      }
    })();

    const showAudioSplash = !audioReady && (
      activeExercise === 'interval' || activeExercise === 'chord' || activeExercise === 'scale'
    );

    return (
      <div style={{ fontFamily: "'Plus Jakarta Sans', sans-serif", maxWidth: 980, margin: '0 auto', paddingBottom: 80 }}>
        {/* Beta banner */}
        <div style={{
          background: 'oklch(96% 0.04 265)',
          border: '1px solid oklch(85% 0.06 265)',
          color: 'oklch(28% 0.1 265)',
          borderRadius: 12,
          padding: '12px 16px',
          fontSize: 12.5,
          marginBottom: 16,
          display: 'flex',
          alignItems: 'center',
          gap: 10,
          flexWrap: 'wrap',
        }}>
          <strong style={{ fontWeight: 700 }}>Beta — admin only.</strong>
          <span style={{ opacity: 0.85 }}>Music theory exercises. Mic-based detection coming later.</span>
        </div>

        {/* Mode toggle */}
        <div style={{ marginBottom: 18 }}>
          <div style={{ fontSize: 11, color: 'oklch(55% 0.04 265)', fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase', marginBottom: 8 }}>Mode</div>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
            {MODES.map(function (m) {
              return (
                <Pill key={m.id} active={mode === m.id} onClick={function () { setMode(m.id); }}>{m.label}</Pill>
              );
            })}
          </div>
        </div>

        {mode === 'curriculum' && window.PracticeLab.ui.CurriculumView && (
          <window.PracticeLab.ui.CurriculumView />
        )}

        {mode === 'free' && (
          <React.Fragment>
            {/* Free practice — the shuffle mode shipped with v95. */}
            <div style={{ display: 'flex', flexDirection: 'column', gap: 12, marginBottom: 18 }}>
              <div>
                <div style={{ fontSize: 11, color: 'oklch(55% 0.04 265)', fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase', marginBottom: 8 }}>Difficulty</div>
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
                  {DIFFICULTIES.map(function (d) {
                    return (
                      <Pill key={d.id} active={difficulty === d.id} onClick={function () { handlePickDifficulty(d.id); }}>{d.label}</Pill>
                    );
                  })}
                </div>
              </div>
              <div>
                <div style={{ fontSize: 11, color: 'oklch(55% 0.04 265)', fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase', marginBottom: 8 }}>Exercise</div>
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>
                  {EXERCISES.map(function (e) {
                    return (
                      <Pill key={e.id} active={exercise === e.id} onClick={function () { handlePickExercise(e.id); }}>{e.label}</Pill>
                    );
                  })}
                </div>
              </div>
            </div>

            {/* Session HUD */}
            <div style={{ display: 'flex', gap: 10, marginBottom: 16, flexWrap: 'wrap' }}>
              <StatTile label="This session" value={sessionScore.total === 0 ? '0 / 0' : sessionScore.correct + ' / ' + sessionScore.total} sub={sessionScore.total === 0 ? 'No attempts yet' : Math.round((sessionScore.correct / sessionScore.total) * 100) + '% correct'} />
              <StatTile label="Current streak" value={String(streak)} sub={streak === 0 ? 'Get one right' : 'In a row'} />
            </div>

            {/* Audio splash */}
            {showAudioSplash && <EnableSoundSplash onEnable={enableSound} />}

            {/* Exercise card */}
            <div style={{
              background: '#fff',
              border: '1px solid oklch(92% 0.012 265)',
              borderRadius: 14,
              padding: 22,
              minHeight: 320,
            }}>
              {!ExerciseComponent && (
                <div style={{ padding: 40, textAlign: 'center', color: 'oklch(55% 0.04 265)', fontSize: 13 }}>Loading exercise…</div>
              )}
              {ExerciseComponent && (
                <ExerciseComponent
                  key={roundKey + ':' + activeExercise + ':' + difficulty}
                  difficulty={difficulty}
                  onAttempt={handleAttempt}
                  onNext={handleNext}
                />
              )}
            </div>

            {/* Lifetime stats footer */}
            <div style={{
              marginTop: 22,
              padding: '14px 18px',
              background: 'oklch(98% 0.005 265)',
              border: '1px solid oklch(92% 0.012 265)',
              borderRadius: 12,
              display: 'flex',
              gap: 22,
              flexWrap: 'wrap',
            }}>
              <div style={{ fontSize: 11, color: 'oklch(55% 0.04 265)', fontWeight: 700, letterSpacing: '0.04em', textTransform: 'uppercase', alignSelf: 'center' }}>Lifetime</div>
              <div><strong style={{ fontWeight: 700 }}>{stats.totalAttempts}</strong> <span style={{ color: 'oklch(55% 0.04 265)', fontSize: 12 }}>attempts</span></div>
              <div><strong style={{ fontWeight: 700 }}>{stats.accuracy}%</strong> <span style={{ color: 'oklch(55% 0.04 265)', fontSize: 12 }}>accuracy</span></div>
              <div><strong style={{ fontWeight: 700 }}>{stats.bestStreak}</strong> <span style={{ color: 'oklch(55% 0.04 265)', fontSize: 12 }}>best streak</span></div>
            </div>
          </React.Fragment>
        )}

        {/* Floating feedback widget */}
        {window.PracticeLab.ui.FeedbackWidget && (
          <window.PracticeLab.ui.FeedbackWidget
            exerciseType={activeExercise}
            getContext={function () { return lastContext.current; }}
          />
        )}
      </div>
    );
  };

  window.PracticeLab.ui.PracticeLab = PracticeLab;
})();
