/* global React, window */
// Practice Lab — curriculum view.
//
// Three sub-views:
//   1. ChapterList — default. Shows each chapter as a card with a
//      progress bar (lessons complete / total). Clicking a chapter
//      expands to show its lessons inline; clicking a lesson enters
//      the lesson runner.
//   2. LessonRunner — for 'lesson' kind. Renders <LessonPage> wrapping
//      the body component named by lesson.component, plus Mark
//      complete + Continue to next lesson.
//   3. ExerciseRunner — for 'exercise' kind. Wraps the chosen exercise
//      component, counts questions, on N attempts shows the score and
//      a Mark complete + Retake action row.

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

  const PRIMARY     = 'oklch(35% 0.16 265)';
  const PRIMARY_BG  = 'oklch(96% 0.04 265)';
  const PRIMARY_BD  = 'oklch(85% 0.06 265)';
  const TEXT_DARK   = 'oklch(18% 0.03 265)';
  const TEXT_MUTED  = 'oklch(55% 0.04 265)';
  const SURFACE     = '#fff';
  const SURFACE_BD  = 'oklch(92% 0.012 265)';
  const SUCCESS     = 'oklch(48% 0.13 152)';
  const SUCCESS_BG  = 'oklch(96% 0.03 152)';

  // ── ChapterList ────────────────────────────────────────────────────
  const ChapterList = function (props) {
    const curriculum = window.PracticeLab.curriculum;
    const chapters = curriculum.CHAPTERS;
    const completedSet = props.completedSet || {};
    const [expanded, setExpanded] = React.useState(chapters[0] && chapters[0].id);

    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        <div style={{ fontSize: 13, color: TEXT_MUTED, lineHeight: 1.55 }}>
          Work your way through the chapters in order, or jump into any lesson you want. Your progress saves automatically when you mark a lesson complete.
        </div>
        {chapters.map(function (ch) {
          const prog = curriculum.chapterProgress(ch.id, completedSet);
          const pct = prog.total === 0 ? 0 : Math.round((prog.done / prog.total) * 100);
          const isExpanded = expanded === ch.id;
          return (
            <div
              key={ch.id}
              style={{
                background: SURFACE,
                border: '1px solid ' + SURFACE_BD,
                borderRadius: 14,
                overflow: 'hidden',
              }}
            >
              <button
                onClick={function () { setExpanded(isExpanded ? null : ch.id); }}
                style={{
                  width: '100%',
                  textAlign: 'left',
                  background: 'transparent',
                  border: 'none',
                  padding: '18px 20px',
                  cursor: 'pointer',
                  fontFamily: "'Plus Jakarta Sans', sans-serif",
                }}
              >
                <div style={{ display: 'flex', alignItems: 'center', gap: 14, flexWrap: 'wrap' }}>
                  <div style={{ flex: 1, minWidth: 180 }}>
                    <div style={{ fontSize: 11, color: TEXT_MUTED, fontWeight: 700, letterSpacing: '0.06em', textTransform: 'uppercase', marginBottom: 4 }}>
                      Chapter
                    </div>
                    <div style={{ fontSize: 18, fontWeight: 700, color: TEXT_DARK, lineHeight: 1.25 }}>
                      {ch.title}
                    </div>
                    <div style={{ fontSize: 13, color: TEXT_MUTED, marginTop: 4, lineHeight: 1.45 }}>
                      {ch.blurb}
                    </div>
                  </div>
                  <div style={{ minWidth: 140, textAlign: 'right' }}>
                    <div style={{ fontSize: 12, color: TEXT_MUTED, fontWeight: 700, letterSpacing: '0.04em', textTransform: 'uppercase' }}>
                      {prog.done} / {prog.total} lessons
                    </div>
                    <div style={{
                      marginTop: 6,
                      height: 6,
                      width: 140,
                      borderRadius: 999,
                      background: 'oklch(94% 0.01 265)',
                      overflow: 'hidden',
                      display: 'inline-block',
                    }}>
                      <div style={{
                        width: pct + '%',
                        height: '100%',
                        background: pct === 100 ? SUCCESS : PRIMARY,
                        transition: 'width 0.25s',
                      }} />
                    </div>
                  </div>
                </div>
              </button>
              {isExpanded && (
                <div style={{ borderTop: '1px solid ' + SURFACE_BD, padding: '6px 0' }}>
                  {ch.lessons.map(function (l, idx) {
                    const done = !!completedSet[l.id];
                    const isExercise = l.kind === 'exercise';
                    return (
                      <button
                        key={l.id}
                        onClick={function () { props.onPickLesson(ch.id, l.id); }}
                        style={{
                          width: '100%',
                          textAlign: 'left',
                          background: 'transparent',
                          border: 'none',
                          borderTop: idx === 0 ? 'none' : '1px solid ' + SURFACE_BD,
                          padding: '12px 20px',
                          cursor: 'pointer',
                          fontFamily: "'Plus Jakarta Sans', sans-serif",
                          display: 'flex',
                          alignItems: 'center',
                          gap: 12,
                        }}
                      >
                        <div style={{
                          width: 28,
                          height: 28,
                          borderRadius: 999,
                          background: done ? SUCCESS : (isExercise ? PRIMARY_BG : 'oklch(98% 0.005 265)'),
                          border: '1px solid ' + (done ? SUCCESS : PRIMARY_BD),
                          color: done ? '#fff' : PRIMARY,
                          fontSize: 12,
                          fontWeight: 800,
                          display: 'flex',
                          alignItems: 'center',
                          justifyContent: 'center',
                          flexShrink: 0,
                        }}>{done ? '✓' : (isExercise ? '?' : '☰')}</div>
                        <div style={{ flex: 1, minWidth: 0 }}>
                          <div style={{ fontSize: 14.5, fontWeight: 700, color: TEXT_DARK, lineHeight: 1.3 }}>
                            {l.title}
                          </div>
                          <div style={{ fontSize: 12.5, color: TEXT_MUTED, marginTop: 2, lineHeight: 1.4 }}>
                            {l.blurb}
                          </div>
                        </div>
                        <div style={{ color: TEXT_MUTED, fontSize: 18, flexShrink: 0 }} aria-hidden="true">→</div>
                      </button>
                    );
                  })}
                </div>
              )}
            </div>
          );
        })}
      </div>
    );
  };

  // ── ExerciseRunner ─────────────────────────────────────────────────
  function exerciseComponentFor(exerciseType) {
    var ui = window.PracticeLab.ui;
    switch (exerciseType) {
      case 'interval':       return ui.ExerciseInterval;
      case 'chord':          return ui.ExerciseChord;
      case 'note_staff':     return ui.ExerciseNoteStaff;
      case 'key_signature':  return ui.ExerciseKeySignature;
      case 'scale':          return ui.ExerciseScale;
      case 'bass_note':      return ui.ExerciseBassNote;
      case 'time_signature': return ui.ExerciseTimeSignature;
      case 'rhythm_match':   return ui.ExerciseRhythmMatch;
      default:               return null;
    }
  }

  const ExerciseRunner = function (props) {
    const lesson = props.lesson;
    const onBack = props.onBack || function () {};
    const onMarkComplete = props.onMarkComplete || function () { return Promise.resolve(); };
    const completed = !!props.completed;
    const goal = (lesson && lesson.questionGoal) || 8;

    const [count, setCount] = React.useState(0);
    const [correct, setCorrect] = React.useState(0);
    const [roundKey, setRoundKey] = React.useState(0);
    const [done, setDone] = React.useState(false);
    const [marking, setMarking] = React.useState(false);

    // Mirror count in a ref so handleNext can read it synchronously
    // without nesting setState calls inside a setCount updater (React's
    // contract says updater functions must be pure; StrictMode would
    // double-invoke them and fire the next-round bump twice).
    const countRef = React.useRef(0);

    const Component = exerciseComponentFor(lesson && lesson.exerciseType);

    const handleAttempt = React.useCallback(async function (attempt) {
      countRef.current += 1;
      setCount(countRef.current);
      if (attempt && attempt.wasCorrect) {
        setCorrect(function (c) { return c + 1; });
      }
      // Persist the per-question row exactly like Free practice does.
      try { await window.PracticeLab.db.recordAttempt(attempt); } catch (e) {}
    }, []);

    const handleNext = React.useCallback(function () {
      if (countRef.current >= goal) {
        setDone(true);
      } else {
        setRoundKey(function (k) { return k + 1; });
      }
    }, [goal]);

    const handleMark = React.useCallback(async function () {
      if (marking || completed) return;
      setMarking(true);
      try { await onMarkComplete(); } finally { setMarking(false); }
    }, [marking, completed, onMarkComplete]);

    const handleRetake = React.useCallback(function () {
      countRef.current = 0;
      setCount(0);
      setCorrect(0);
      setDone(false);
      setRoundKey(function (k) { return k + 1; });
    }, []);

    const accuracy = count > 0 ? Math.round((correct / count) * 100) : 0;

    return (
      <div style={{ fontFamily: "'Plus Jakarta Sans', sans-serif", maxWidth: 760, margin: '0 auto', paddingBottom: 32 }}>
        <button
          onClick={onBack}
          style={{
            display: 'inline-flex',
            alignItems: 'center',
            gap: 6,
            background: 'transparent',
            border: 'none',
            color: TEXT_MUTED,
            fontSize: 12.5,
            fontWeight: 600,
            padding: '6px 0',
            marginBottom: 6,
            cursor: 'pointer',
            fontFamily: "'Plus Jakarta Sans', sans-serif",
          }}
        >
          <span aria-hidden="true">←</span>
          <span>Back to chapter</span>
        </button>
        <div style={{ fontSize: 11.5, color: TEXT_MUTED, fontWeight: 700, letterSpacing: '0.06em', textTransform: 'uppercase', marginBottom: 4 }}>
          {props.chapterTitle || 'Practice'}
        </div>
        <h1 style={{ margin: 0, fontSize: 26, fontWeight: 700, color: TEXT_DARK, lineHeight: 1.25 }}>
          {lesson && lesson.title}
        </h1>
        {lesson && lesson.blurb && (
          <p style={{ marginTop: 8, marginBottom: 0, fontSize: 14, color: TEXT_MUTED, lineHeight: 1.5 }}>{lesson.blurb}</p>
        )}

        {/* Progress strip */}
        <div style={{ display: 'flex', gap: 10, marginTop: 18, marginBottom: 14, flexWrap: 'wrap' }}>
          <div style={{
            flex: 1, minWidth: 140,
            background: SURFACE, border: '1px solid ' + SURFACE_BD,
            borderRadius: 12, padding: '12px 16px',
          }}>
            <div style={{ fontSize: 11, color: TEXT_MUTED, fontWeight: 700, letterSpacing: '0.04em', textTransform: 'uppercase' }}>Question</div>
            <div style={{ fontSize: 20, fontWeight: 700, color: TEXT_DARK, lineHeight: 1.1, marginTop: 4 }}>
              {Math.min(count + (done ? 0 : 1), goal)} / {goal}
            </div>
          </div>
          <div style={{
            flex: 1, minWidth: 140,
            background: SURFACE, border: '1px solid ' + SURFACE_BD,
            borderRadius: 12, padding: '12px 16px',
          }}>
            <div style={{ fontSize: 11, color: TEXT_MUTED, fontWeight: 700, letterSpacing: '0.04em', textTransform: 'uppercase' }}>Score</div>
            <div style={{ fontSize: 20, fontWeight: 700, color: TEXT_DARK, lineHeight: 1.1, marginTop: 4 }}>
              {correct} / {count}{count > 0 && <span style={{ fontSize: 13, fontWeight: 600, color: TEXT_MUTED, marginLeft: 8 }}>{accuracy}%</span>}
            </div>
          </div>
        </div>

        {/* Exercise card OR completion card */}
        <div style={{
          background: SURFACE, border: '1px solid ' + SURFACE_BD,
          borderRadius: 14, padding: 22, minHeight: 280,
        }}>
          {!done && Component && (
            <Component
              key={roundKey}
              difficulty={lesson.difficulty || 'beginner'}
              onAttempt={handleAttempt}
              onNext={handleNext}
            />
          )}
          {!done && !Component && (
            <div style={{ padding: 40, textAlign: 'center', color: TEXT_MUTED, fontSize: 13 }}>
              Exercise component not available — try refreshing.
            </div>
          )}
          {done && (
            <div style={{ textAlign: 'center', padding: '12px 8px' }}>
              <div style={{ fontSize: 13, color: TEXT_MUTED, fontWeight: 700, letterSpacing: '0.05em', textTransform: 'uppercase' }}>Quiz complete</div>
              <div style={{ fontSize: 36, fontWeight: 800, color: TEXT_DARK, marginTop: 6 }}>{correct} / {count}</div>
              <div style={{ fontSize: 14, color: TEXT_MUTED, marginTop: 4 }}>{accuracy}% correct</div>
              <div style={{ marginTop: 22, display: 'flex', gap: 10, justifyContent: 'center', flexWrap: 'wrap' }}>
                <button
                  onClick={handleMark}
                  disabled={completed || marking}
                  style={{
                    padding: '11px 22px',
                    borderRadius: 10,
                    border: 'none',
                    background: completed ? SURFACE_BD : PRIMARY,
                    color: completed ? TEXT_MUTED : '#fff',
                    fontSize: 14,
                    fontWeight: 700,
                    cursor: (completed || marking) ? 'default' : 'pointer',
                    fontFamily: "'Plus Jakarta Sans', sans-serif",
                  }}
                >{completed ? 'Marked complete' : (marking ? 'Saving…' : 'Mark complete')}</button>
                <button
                  onClick={handleRetake}
                  style={{
                    padding: '11px 22px',
                    borderRadius: 10,
                    border: '1px solid ' + PRIMARY_BD,
                    background: PRIMARY_BG,
                    color: PRIMARY,
                    fontSize: 14,
                    fontWeight: 700,
                    cursor: 'pointer',
                    fontFamily: "'Plus Jakarta Sans', sans-serif",
                  }}
                >Retake</button>
                <button
                  onClick={onBack}
                  style={{
                    padding: '11px 22px',
                    borderRadius: 10,
                    border: '1px solid ' + SURFACE_BD,
                    background: '#fff',
                    color: TEXT_DARK,
                    fontSize: 14,
                    fontWeight: 700,
                    cursor: 'pointer',
                    fontFamily: "'Plus Jakarta Sans', sans-serif",
                  }}
                >Back to chapter</button>
              </div>
            </div>
          )}
        </div>
      </div>
    );
  };

  // ── LessonRunner (instructional) ───────────────────────────────────
  const LessonRunner = function (props) {
    const lesson = props.lesson;
    const LessonPage = window.PracticeLab.ui.LessonPage;
    const BodyComp = lesson && lesson.component && window.PracticeLab.ui[lesson.component];
    return (
      <LessonPage
        title={lesson && lesson.title}
        intro={lesson && lesson.blurb}
        chapterTitle={props.chapterTitle}
        completed={!!props.completed}
        onMarkComplete={props.onMarkComplete}
        onBack={props.onBack}
        onNext={props.onContinue}
        hasNext={!!props.hasNext}
      >
        {BodyComp ? <BodyComp /> : (
          <div style={{ padding: 24, color: TEXT_MUTED, fontSize: 13 }}>
            This lesson's content is missing — try refreshing the page.
          </div>
        )}
      </LessonPage>
    );
  };

  // ── CurriculumView (top-level) ─────────────────────────────────────
  const CurriculumView = function () {
    const curriculum = window.PracticeLab.curriculum;
    const [route, setRoute] = React.useState({ view: 'chapters', chapterId: null, lessonId: null });
    const [completedSet, setCompletedSet] = React.useState({});

    const reloadProgress = React.useCallback(async function () {
      try {
        var map = await window.PracticeLab.db.getLessonProgress();
        setCompletedSet(map || {});
      } catch (e) { setCompletedSet({}); }
    }, []);

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

    const enterLesson = React.useCallback(function (chapterId, lessonId) {
      setRoute({ view: 'lesson', chapterId: chapterId, lessonId: lessonId });
    }, []);

    const backToChapters = React.useCallback(function () {
      setRoute({ view: 'chapters', chapterId: null, lessonId: null });
    }, []);

    const lessonContext = React.useMemo(function () {
      if (route.view !== 'lesson' || !route.chapterId || !route.lessonId) return null;
      var ch = curriculum.getChapter(route.chapterId);
      if (!ch) return null;
      var idx = -1;
      for (var i = 0; i < ch.lessons.length; i++) {
        if (ch.lessons[i].id === route.lessonId) { idx = i; break; }
      }
      if (idx === -1) return null;
      return {
        chapter: ch,
        lesson: ch.lessons[idx],
        nextLesson: idx + 1 < ch.lessons.length ? ch.lessons[idx + 1] : null,
      };
    }, [route, curriculum]);

    const [saveError, setSaveError] = React.useState(null);

    const markCurrentComplete = React.useCallback(async function () {
      if (!lessonContext) return;
      setSaveError(null);
      var res = await window.PracticeLab.db.markLessonComplete(lessonContext.lesson.id);
      if (res && res.ok) {
        setCompletedSet(function (prev) {
          var next = Object.assign({}, prev);
          next[lessonContext.lesson.id] = new Date().toISOString();
          return next;
        });
      } else {
        // Surface the failure instead of silently dropping the click.
        // Reasons we might see this: lost auth, network blip, RLS denial.
        setSaveError((res && res.error) || 'Could not save progress.');
      }
    }, [lessonContext]);

    const continueToNext = React.useCallback(function () {
      if (!lessonContext || !lessonContext.nextLesson) {
        backToChapters();
        return;
      }
      setRoute({
        view: 'lesson',
        chapterId: lessonContext.chapter.id,
        lessonId: lessonContext.nextLesson.id,
      });
    }, [lessonContext, backToChapters]);

    // Toast renderer for save errors. Mounted alongside whichever
    // inner view is active so it overlays both lesson + exercise runs.
    const ErrorToast = saveError ? (
      <div
        role="alert"
        style={{
          position: 'fixed',
          top: 20,
          left: '50%',
          transform: 'translateX(-50%)',
          background: 'oklch(58% 0.18 25)',
          color: '#fff',
          padding: '10px 18px',
          borderRadius: 10,
          fontSize: 13.5,
          fontWeight: 600,
          fontFamily: "'Plus Jakarta Sans', sans-serif",
          boxShadow: '0 6px 20px rgba(0,0,0,0.15)',
          zIndex: 9999,
          maxWidth: 460,
        }}
      >
        <strong style={{ fontWeight: 700 }}>Save failed:</strong> {saveError}
        <button
          onClick={function () { setSaveError(null); }}
          style={{
            marginLeft: 12,
            background: 'transparent',
            border: '1px solid #fff',
            color: '#fff',
            padding: '2px 8px',
            borderRadius: 6,
            fontSize: 12,
            fontWeight: 700,
            cursor: 'pointer',
            fontFamily: "'Plus Jakarta Sans', sans-serif",
          }}
        >Dismiss</button>
      </div>
    ) : null;

    if (route.view === 'lesson' && lessonContext) {
      var lesson = lessonContext.lesson;
      var completed = !!completedSet[lesson.id];
      if (lesson.kind === 'exercise') {
        return (
          <React.Fragment>
            {ErrorToast}
            <ExerciseRunner
              key={lesson.id}
              lesson={lesson}
              chapterTitle={lessonContext.chapter.title}
              completed={completed}
              onMarkComplete={markCurrentComplete}
              onBack={backToChapters}
            />
          </React.Fragment>
        );
      }
      return (
        <React.Fragment>
          {ErrorToast}
          <LessonRunner
            key={lesson.id}
            lesson={lesson}
            chapterTitle={lessonContext.chapter.title}
            completed={completed}
            onMarkComplete={markCurrentComplete}
            onBack={backToChapters}
            onContinue={continueToNext}
            hasNext={!!lessonContext.nextLesson}
          />
        </React.Fragment>
      );
    }

    return (
      <React.Fragment>
        {ErrorToast}
        <ChapterList completedSet={completedSet} onPickLesson={enterLesson} />
      </React.Fragment>
    );
  };

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