// ─────────────────────────────────────────────────────────
// ChefVerse · Lesson progress store (V3 — nested + typed)
//
// Tracks completion by lesson ID (stable across nesting changes).
// Completion rules per type:
//   video    → marked when watched to end       (markLessonDone)
//   written  → marked on scroll-to-bottom        (markLessonDone)
//   graphic  → marked on view/mount              (markLessonDone)
//   carousel → marked when all cards seen         (markLessonDone after carousel-all)
//
// Sequential unlock preserved at the MODULE level:
//   Module N+1 unlocks only when Module N is 100% complete.
// Within a module, lessons can be taken in any order.
//
// Persists to localStorage. New chefs start empty; the experienced
// profile is seeded with believable mid-flight progress.
// ─────────────────────────────────────────────────────────

const LP_KEY = "chefverse.lessonprogress.v1";

let _lpState = null;
const _lpListeners = new Set();

function _lpDetectNewProfile() {
  try {
    if (typeof window !== "undefined" && window.__CHEF_PROFILE__) {
      return window.__CHEF_PROFILE__ === "new";
    }
  } catch (e) {}
  return false;
}

// Seed: experienced chef has Module 1 done + Module 2.1 fully done + part of 2.2.
function _lpSeed() {
  const done = {};
  if (_lpDetectNewProfile()) return { done };
  const cur = window.CURRICULUM || [];
  const markAll = (mod) => {
    (mod.directLessons || []).forEach(l => { done[l.id] = true; });
    (mod.subModules || []).forEach(sm => sm.lessons.forEach(l => { done[l.id] = true; }));
  };
  // Module 1 fully done
  const m1 = cur.find(m => m.id === "m1");
  if (m1) markAll(m1);
  // Module 2: direct lesson + 2.1 done, 2.2 partially
  const m2 = cur.find(m => m.id === "m2");
  if (m2) {
    (m2.directLessons || []).forEach(l => { done[l.id] = true; });
    const sm21 = (m2.subModules || []).find(s => s.id === "m2-1");
    if (sm21) sm21.lessons.forEach(l => { done[l.id] = true; });
    const sm22 = (m2.subModules || []).find(s => s.id === "m2-2");
    if (sm22) { done[sm22.lessons[0].id] = true; done[sm22.lessons[1].id] = true; }
  }
  return { done };
}

function _lpLoad() {
  try {
    const raw = localStorage.getItem(LP_KEY);
    if (raw) {
      const parsed = JSON.parse(raw);
      if (parsed && parsed.done) return parsed;
    }
  } catch (e) {}
  return _lpSeed();
}

function _lpSave(state) {
  try { localStorage.setItem(LP_KEY, JSON.stringify(state)); } catch (e) {}
}

function _lpEnsure() { if (!_lpState) _lpState = _lpLoad(); return _lpState; }
function _lpSet(updater) {
  _lpState = typeof updater === "function" ? updater(_lpEnsure()) : updater;
  _lpSave(_lpState);
  _lpListeners.forEach(l => l(_lpState));
}

// ── pure readers ──
function _lpIsDone(state, lessonId) { return !!state.done[lessonId]; }

function _lpModuleCounts(state, mod) {
  const all = window.flattenModuleLessons(mod);
  const total = all.length;
  let done = 0;
  all.forEach(({ lesson }) => { if (state.done[lesson.id]) done++; });
  return { done, total };
}

function _lpModulePct(state, mod) {
  const { done, total } = _lpModuleCounts(state, mod);
  return total === 0 ? 0 : done / total;
}

// Module status with sequential unlock: locked until all prior modules 100%.
function _lpModuleStatus(state, modIdx) {
  const cur = window.CURRICULUM || [];
  for (let i = 0; i < modIdx; i++) {
    if (_lpModulePct(state, cur[i]) < 1) return "locked";
  }
  const pct = _lpModulePct(state, cur[modIdx]);
  if (pct >= 1) return "done";
  if (pct > 0) return "current";
  return "next";
}

function _lpSubModuleCounts(state, sm) {
  const total = (sm.lessons || []).length;
  let done = 0;
  (sm.lessons || []).forEach(l => { if (state.done[l.id]) done++; });
  return { done, total };
}

// First unfinished lesson in a module (flat order) — for "Resume"
function _lpFirstUnfinished(state, mod) {
  const all = window.flattenModuleLessons(mod);
  for (const entry of all) {
    if (!state.done[entry.lesson.id]) return entry;
  }
  return all[0] || null;
}


// Direct-content completion: are all of a module's direct lessons done?
function _lpDirectDone(state, mod) {
  const direct = mod.directLessons || [];
  if (direct.length === 0) return true; // no direct content → nothing gating sub-modules
  return direct.every(l => state.done[l.id]);
}

// Sub-module status with the unlock rules:
//   locked  → module's direct content not finished, OR a prior sub-module not finished
//   done    → all lessons in this sub-module complete
//   current → unlocked & partially done
//   next    → unlocked & not started
function _lpSubStatus(state, mod, subIdx) {
  if (!_lpDirectDone(state, mod)) return "locked";
  const subs = mod.subModules || [];
  for (let i = 0; i < subIdx; i++) {
    const c = _lpSubModuleCounts(state, subs[i]);
    if (c.done < c.total) return "locked";
  }
  const c = _lpSubModuleCounts(state, subs[subIdx]);
  if (c.total > 0 && c.done === c.total) return "done";
  if (c.done > 0) return "current";
  return "next";
}

// Is a single lesson locked? (used by the lesson rows)
//   Direct lessons: never locked once the module is unlocked.
//   Sub-module lessons: locked if their sub-module is locked.
function _lpLessonLocked(state, mod, entry) {
  if (entry.subModule == null) return false;        // direct lesson
  const subIdx = (mod.subModules || []).findIndex(s => s.id === entry.subModule.id);
  return _lpSubStatus(state, mod, subIdx) === "locked";
}

// Hub (Shape C) hero button resolver. The hub module is intro-only — all learning
// lives in the sub-modules — so the button always targets a sub-module.
// Returns { state, target:{ kind:"sub", subId } }:
//   state: "review" (all sub-modules done) | "continue" (one in progress / next unlocked) | "start" (nothing started)
function _lpHubContinue(state, mod) {
  const subs = mod.subModules || [];
  if (subs.length === 0) return { state: "start", target: { kind: "sub", subId: null } };

  const allSubsDone = subs.every(sm => {
    const c = _lpSubModuleCounts(state, sm); return c.total > 0 && c.done === c.total;
  });
  const anyStarted = subs.some(sm => _lpSubModuleCounts(state, sm).done > 0);

  // 1. Everything complete → Review → first sub-module
  if (allSubsDone) {
    return { state: "review", target: { kind: "sub", subId: subs[0].id } };
  }
  // 2. A sub-module is in progress → Continue → that sub-module
  for (let i = 0; i < subs.length; i++) {
    const c = _lpSubModuleCounts(state, subs[i]);
    if (c.done > 0 && c.done < c.total) {
      return { state: "continue", target: { kind: "sub", subId: subs[i].id } };
    }
  }
  // 3. Next unlocked, not-started sub-module → Continue (or Start if nothing started yet)
  for (let i = 0; i < subs.length; i++) {
    const st = _lpSubStatus(state, mod, i);
    const c = _lpSubModuleCounts(state, subs[i]);
    if (st !== "locked" && c.done === 0) {
      return { state: anyStarted ? "continue" : "start", target: { kind: "sub", subId: subs[i].id } };
    }
  }
  // Fallback → first sub-module
  return { state: "start", target: { kind: "sub", subId: subs[0].id } };
}

// ── Dashboard "Next up in your path" resolver ──
// Produces a flat, ordered list of "step" cards across the whole curriculum,
// where each step is a MODULE (flat, shapes A/B) or a SUB-MODULE (parts of a
// hub, shape C). Hub modules contribute their sub-modules as steps (the hub
// itself is intro-only). Each card always has a real thumbnail.
//
// Card shape:
//   { key, kind:"module"|"sub", modId, subId?, num, title, thumb,
//     pct, status:"done"|"current"|"next"|"locked", lessons }
function _lpDashSteps(state) {
  const cur = window.CURRICULUM || [];
  const steps = [];
  cur.forEach((mod, mi) => {
    const modStatus = _lpModuleStatus(state, mi);
    const subs = mod.subModules || [];
    if (subs.length > 0) {
      // Hub → each sub-module is a step
      subs.forEach((sm, si) => {
        const c = _lpSubModuleCounts(state, sm);
        const pct = c.total ? c.done / c.total : 0;
        let status;
        if (modStatus === "locked") status = "locked";
        else status = _lpSubStatus(state, mod, si); // done | current | next | locked
        steps.push({
          key: sm.id, kind: "sub", modId: mod.id, subId: sm.id,
          num: sm.num, title: sm.title, thumb: sm.thumb || mod.thumb,
          pct, status, lessons: c.total,
        });
      });
    } else {
      // Flat module → the module is the step
      const c = _lpModuleCounts(state, mod);
      const pct = _lpModulePct(state, mod);
      let status;
      if (modStatus === "locked") status = "locked";
      else if (pct >= 1) status = "done";
      else if (pct > 0) status = "current";
      else status = "next";
      steps.push({
        key: mod.id, kind: "module", modId: mod.id,
        num: mod.num, title: mod.title, thumb: mod.thumb,
        pct, status, lessons: c.total,
      });
    }
  });
  return steps;
}

// Featured = the step the chef should resume (first current → first available
// not-done → first). Up-next = the following not-done steps. New chef (nothing
// started) → featured is the first step at 0%, up-next the next two.
function _lpDashboardNext(state, upNextCount) {
  const steps = _lpDashSteps(state);
  if (steps.length === 0) return { featured: null, upNext: [] };
  let fIdx = steps.findIndex(s => s.status === "current");
  if (fIdx < 0) fIdx = steps.findIndex(s => s.status !== "done" && s.status !== "locked");
  if (fIdx < 0) fIdx = steps.findIndex(s => s.status !== "done");
  if (fIdx < 0) fIdx = 0; // everything done → feature the first (Review)
  const featured = steps[fIdx];
  const upNext = [];
  for (let i = fIdx + 1; i < steps.length && upNext.length < (upNextCount || 2); i++) {
    upNext.push(steps[i]);
  }
  return { featured, upNext };
}

function useLessonProgress() {
  const [, force] = React.useState(0);
  React.useEffect(() => {
    const fn = () => force(n => n + 1);
    _lpListeners.add(fn);
    return () => _lpListeners.delete(fn);
  }, []);
  const state = _lpEnsure();
  return {
    isDone: (lessonId) => _lpIsDone(state, lessonId),
    moduleCounts: (mod) => _lpModuleCounts(state, mod),
    modulePct: (mod) => _lpModulePct(state, mod),
    moduleStatus: (modIdx) => _lpModuleStatus(state, modIdx),
    subModuleCounts: (sm) => _lpSubModuleCounts(state, sm),
    firstUnfinished: (mod) => _lpFirstUnfinished(state, mod),
    directDone: (mod) => _lpDirectDone(state, mod),
    subStatus: (mod, subIdx) => _lpSubStatus(state, mod, subIdx),
    lessonLocked: (mod, entry) => _lpLessonLocked(state, mod, entry),
    hubContinue: (mod) => _lpHubContinue(state, mod),
    dashboardNext: (n) => _lpDashboardNext(state, n),
    markDone: (lessonId) => _lpSet(s => ({ ...s, done: { ...s.done, [lessonId]: true } })),
    reset: () => _lpSet(_lpSeed()),
    _state: state,
  };
}

window.useLessonProgress = useLessonProgress;
window.markLessonDone = (lessonId) => _lpSet(s => ({ ...s, done: { ...s.done, [lessonId]: true } }));
window.resetLessonProgress = () => _lpSet(_lpSeed());
