/* global React, ReactDOM,
   CoursePicker, Home, QuizSetup, QuizSession, Results, Dashboard, Cheatsheet */
const { useState, useEffect, useMemo } = React;

function App() {
  const theme = 'sunset';
  const [route, setRoute] = useState({ name: 'course-picker', params: {} });
  const [courseId, setCourseId] = useState(null);
  const [tick, setTick] = useState(0); // bump to force progress re-read after a quiz

  const refresh = () => setTick(t => t + 1);

  // Auto-resume last course on first load
  useEffect(() => {
    const root = window.QuizStorage.getRoot();
    if (root.currentCourseId && window.getRawCourse(root.currentCourseId)) {
      setCourseId(root.currentCourseId);
      setRoute({ name: 'home', params: {} });
    }
  }, []);

  const courseViews = useMemo(() => {
    void tick;
    return window.RAW_COURSES.map(c => window.buildCourseView(c));
  }, [tick]);

  const course = useMemo(
    () => courseViews.find(c => c.id === courseId) || null,
    [courseId, courseViews]
  );

  const navigate = (name, params = {}) => setRoute({ name, params });

  const pickCourse = (c) => {
    window.QuizStorage.setCurrentCourse(c.id);
    setCourseId(c.id);
    navigate('home');
  };

  const switchCourse = () => {
    setCourseId(null);
    navigate('course-picker');
  };

  const startQuiz = (mode, opts = {}) => {
    if (!course) return;
    const { questions: pool, manifest } = course._raw;
    const engine = window.QuizEngine;
    const storage = window.QuizStorage;
    let questions;

    if (mode === 'mock' && manifest.mockExam?.enabled && manifest.mockExam.domainQuotas) {
      questions = engine.stratifiedMockSample(pool, manifest.mockExam.domainQuotas);
    } else if (mode === 'study') {
      const progress = storage.getCourseProgress(course.id);
      const queue = engine.selectStudyQueue(pool, progress.spacedRepetition, new Date(), opts.count || 20);
      // If queue is small (mostly unseen items), pad with random samples
      questions = queue.length >= (opts.count || 20)
        ? queue
        : [...queue, ...engine.sampleQuestions(pool.filter(q => !queue.includes(q)), { count: (opts.count || 20) - queue.length })];
    } else {
      questions = engine.sampleQuestions(pool, { count: opts.count || 25, domain: opts.domain || undefined });
    }

    if (!questions.length) {
      questions = engine.sampleQuestions(pool, { count: 5 });
    }

    navigate('quiz-session', { mode, questions, startedAt: new Date().toISOString() });
  };

  const drillByTag = (tag) => {
    if (!course) return;
    const pool = course._raw.questions.filter(q => q.tags?.includes(tag));
    const questions = window.QuizEngine.sampleQuestions(pool, { count: 20 });
    navigate('quiz-session', { mode: 'drill', questions, startedAt: new Date().toISOString() });
  };

  const drillSingleQuestion = (q) => {
    if (!course) return;
    navigate('quiz-session', {
      mode: 'drill',
      questions: [q],
      startedAt: new Date().toISOString(),
    });
  };

  const finishQuiz = ({ answers, questions }) => {
    if (!course) return;
    const storage = window.QuizStorage;
    const engine = window.QuizEngine;
    const now = new Date();
    const answeredAt = now.toISOString();

    // Persisted answer log uses first-attempt values so the Results screen and
    // Dashboard "Most missed" reflect what the user got right on first try.
    // Spaced repetition uses last-attempt to avoid double-decaying a
    // missed-then-correct question.
    const persistedAnswers = answers.map(a => ({
      questionId: a.questionId,
      selected: a.selected,
      correct: a.correct,
      answeredAt,
    }));

    for (let i = 0; i < answers.length; i++) {
      const a = answers[i];
      storage.appendAnswer(course.id, persistedAnswers[i]);
      const q = questions.find(qq => qq.id === a.questionId);
      if (!q) continue;
      const prior = storage.getCourseProgress(course.id).spacedRepetition[q.id];
      const lastCorrect = a.lastCorrect ?? a.correct;
      const next = engine.applySpacedRepetition(prior, lastCorrect, now);
      storage.updateSpacedRepetition(course.id, q.id, next);
    }

    storage.appendSession(course.id, {
      mode: route.params.mode,
      startedAt: route.params.startedAt,
      finishedAt: answeredAt,
      totalQuestions: questions.length,
      correctCount: answers.filter(a => a.correct).length,
      answers: persistedAnswers,
    });

    refresh();
    navigate('results', { mode: route.params.mode, answers, questions });
  };

  const exportProgress = () => {
    const json = window.QuizStorage.exportRoot();
    const blob = new Blob([json], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `study-quiz-progress-${new Date().toISOString().slice(0, 10)}.json`;
    a.click();
    URL.revokeObjectURL(url);
  };

  const importProgress = () => {
    const input = document.createElement('input');
    input.type = 'file';
    input.accept = 'application/json,.json';
    input.onchange = async () => {
      const file = input.files?.[0];
      if (!file) return;
      try {
        const text = await file.text();
        window.QuizStorage.importRoot(text);
        refresh();
        alert('Progress imported.');
      } catch (e) {
        alert('Could not import: ' + e.message);
      }
    };
    input.click();
  };

  let screen;
  if (!course || route.name === 'course-picker') {
    screen = <CoursePicker
      courses={courseViews}
      onPickCourse={pickCourse}
      onExport={exportProgress}
      onImport={importProgress}
      theme={theme}
    />;
  } else if (route.name === 'home') {
    screen = <Home
      course={course}
      theme={theme}
      onSwitchCourse={switchCourse}
      onMode={(m) => {
        if (m === 'dashboard')      navigate('dashboard');
        else if (m === 'cheatsheet') navigate('cheatsheet');
        else                         navigate('setup', { mode: m });
      }}
    />;
  } else if (route.name === 'setup') {
    screen = <QuizSetup
      course={course}
      mode={route.params.mode}
      theme={theme}
      onBack={() => navigate('home')}
      onStart={(opts) => startQuiz(route.params.mode, opts)}
    />;
  } else if (route.name === 'quiz-session') {
    screen = <QuizSession
      course={course}
      mode={route.params.mode}
      questions={route.params.questions}
      startedAt={route.params.startedAt}
      theme={theme}
      onExit={() => navigate('home')}
      onFinish={finishQuiz}
    />;
  } else if (route.name === 'results') {
    const missedQs = route.params.answers
      .filter(a => !a.correct)
      .map(a => route.params.questions.find(q => q.id === a.questionId))
      .filter(Boolean);
    screen = <Results
      course={course}
      mode={route.params.mode}
      answers={route.params.answers}
      questions={route.params.questions}
      theme={theme}
      onHome={() => navigate('home')}
      onRestudy={() => navigate('quiz-session', {
        mode: 'study',
        questions: missedQs,
        startedAt: new Date().toISOString(),
      })}
    />;
  } else if (route.name === 'dashboard') {
    screen = <Dashboard
      course={course}
      theme={theme}
      onBack={() => navigate('home')}
      onDrillTag={drillByTag}
      onDrillQuestion={drillSingleQuestion}
    />;
  } else if (route.name === 'cheatsheet') {
    screen = <Cheatsheet course={course} onBack={() => navigate('home')} />;
  }

  return <>{screen}</>;
}

function bootstrap() {
  if (!window.studyQuizReady) {
    window.addEventListener('study-quiz-ready', bootstrap, { once: true });
    return;
  }
  ReactDOM.createRoot(document.getElementById('root')).render(<App />);
}
bootstrap();
