/* ============================================================
   ENERGY PRIMER — React reader
   Renders course home, session pages, and resources.
   ============================================================ */
const { useState: epUse, useEffect: epEffect, useMemo: epMemo, useRef: epRef } = React;

/* ---------- session metadata ---------- */
const EP_SESSIONS = [
  {
    id: "01", file: "primer/session-01.md",
    title: "Energy Foundations & Systems Thinking",
    subtitle: "Units, primary vs. final energy, capacity factor, and the trilemma.",
    blindSpot: "Treating energy as one market instead of a system of distinct subsystems.",
    duration: 120,
    concepts: ["Units & orders of magnitude", "Primary / final / useful", "Stocks vs. flows", "The trilemma", "Capacity factor", "Adequacy vs. flexibility"],
    deliverable: "Country energy snapshot template",
  },
  {
    id: "02", file: "primer/session-02.md",
    title: "Oil & Liquid Fuels Beyond the Futures Curve",
    subtitle: "Upstream, midstream, downstream — the machinery under the price.",
    blindSpot: "Knowing the curve but not the physical and corporate machinery that drives it.",
    duration: 120,
    concepts: ["Value chain economics", "Decline curves", "Crude grades & differentials", "Crack spreads", "OPEC+ as institution", "Demand structure"],
    deliverable: "Sectoral oil demand model",
  },
  {
    id: "03", file: "primer/session-03.md",
    title: "Natural Gas, LNG, and the Most Geopolitical Molecule",
    subtitle: "Why gas is regional, what LNG changes, and what the 2022 crisis taught.",
    blindSpot: "Treating gas as oil-lite. The infrastructure-bound nature makes it different.",
    duration: 120,
    concepts: ["Regional markets & arbitrage", "LNG value chain", "HH / TTF / JKM", "Storage & seasonality", "The transition-fuel debate"],
    deliverable: "LNG project economics model",
  },
  {
    id: "04", file: "primer/session-04.md",
    title: "Power Markets — Where Most Traders Get Surprised",
    subtitle: "Why electricity is not a commodity — and what that implies for design.",
    blindSpot: "Pattern-matching power to oil. Power is an instantaneous service, not inventory.",
    duration: 120,
    concepts: ["The physics constraint", "Merit-order dispatch", "Nodal vs. zonal pricing", "Capacity vs. energy markets", "The duck curve", "Value deflation"],
    deliverable: "Merit-order dispatch model",
  },
  {
    id: "05", file: "primer/session-05.md",
    title: "Renewables Economics Beyond the Headline LCOE",
    subtitle: "WACC is destiny — and why LCOE is necessary but not sufficient.",
    blindSpot: "Treating renewables as a commodity. They are capital projects.",
    duration: 120,
    concepts: ["LCOE from first principles", "Capture price & value deflation", "Cost of capital", "Solar / onshore / offshore", "PPA structures"],
    deliverable: "LCOE model with sensitivity",
  },
  {
    id: "06", file: "primer/session-06.md",
    title: "Storage, Grids, and the Flexibility Constraint",
    subtitle: "The flexibility cost stack — and why transmission matters as much as storage.",
    blindSpot: "Storage as the answer to intermittency. It solves some problems, not others.",
    duration: 120,
    concepts: ["Flexibility timescales", "Li-ion battery economics", "Revenue stack", "Long-duration options", "Transmission & demand response"],
    deliverable: "Battery dispatch optimizer",
  },
  {
    id: "07", file: "primer/session-07.md",
    title: "Decarbonization Pathways — Sectors Are Not Interchangeable",
    subtitle: "Eight sectoral transitions, eight different physics and economics.",
    blindSpot: "Treating 'net zero' as a slogan. It's an engineering problem, by sector.",
    duration: 120,
    concepts: ["MAC curves and their limits", "Power, transport, buildings", "Heavy industry", "Hydrogen's real use cases", "CCUS by source"],
    deliverable: "Corporate MACC",
  },
  {
    id: "08", file: "primer/session-08.md",
    title: "Geopolitics, Critical Minerals, and the New Energy Map",
    subtitle: "The chokepoints moved from oil straits to processing facilities.",
    blindSpot: "Mining vs. processing — the leverage sits midstream, not upstream.",
    duration: 120,
    concepts: ["Three-layer concentration", "China's processing dominance", "IRA, NZIA, CBAM", "Li / Co / Ni / Cu / REEs", "Industrial policy"],
    deliverable: "Critical-minerals risk scorecard",
  },
  {
    id: "09", file: "primer/session-09.md",
    title: "Energy Finance and Corporate Strategy",
    subtitle: "Capital is the binding constraint — and rates are the dominant variable.",
    blindSpot: "Energy companies are not commodity-trading P&Ls. They are long-duration allocators.",
    duration: 120,
    concepts: ["Capital intensity", "Project finance structures", "Utility 2.0 & the major dilemma", "Capital allocation", "TCFD / ISSB"],
    deliverable: "IPP DCF model",
  },
  {
    id: "10", file: "primer/session-10.md",
    title: "Synthesis — From Knowledge to Advisory Practice",
    subtitle: "Turning the framework into a repeatable advisory process.",
    blindSpot: "The temptation to forecast. Clients need defensible scenarios, not point estimates.",
    duration: 120,
    concepts: ["The five question archetypes", "Advisory diagnostic", "Research process", "Sources hierarchy", "Analytical assets"],
    deliverable: "Client memo + research checklist",
  },
];

const EP_RESOURCES = [
  { id: "curriculum",         file: "primer/curriculum.md",           tag: "Overview",   title: "Curriculum overview",      sub: "The 20-hour course at a glance." },
  { id: "course-overview",    file: "primer/course-overview.md",      tag: "Outline",    title: "Detailed course outline",   sub: "Each session's purpose, key numbers, synthesis question." },
  { id: "memo-template",      file: "primer/resource-memo-template.md",   tag: "Template",  title: "Client memo template",     sub: "Briefing, investment, and strategy memo structures." },
  { id: "research-checklist", file: "primer/resource-research-checklist.md", tag: "Practice", title: "Research process checklist", sub: "Daily, weekly, monthly, quarterly rhythms." },
];

/* ---------- progress tracking ---------- */
const EP_PROG_KEY = "energy-primer-progress-v1";
function epLoadProgress() {
  try { return JSON.parse(localStorage.getItem(EP_PROG_KEY) || "{}"); }
  catch { return {}; }
}
function epSaveProgress(p) {
  try { localStorage.setItem(EP_PROG_KEY, JSON.stringify(p)); } catch {}
}

/* ---------- markdown cache + fetcher ---------- */
const EP_MD_CACHE = new Map();
async function epFetchMd(file) {
  if (EP_MD_CACHE.has(file)) return EP_MD_CACHE.get(file);
  const res = await fetch(file);
  if (!res.ok) throw new Error("fetch failed: " + file);
  const text = await res.text();
  EP_MD_CACHE.set(file, text);
  return text;
}

/* ---------- markdown rendering via marked ---------- */
function epRenderMarkdown(md) {
  if (!window.marked) return { html: "<p>Loading markdown library…</p>", toc: [] };

  // Strip H1 (we render our own title block)
  let body = md.replace(/^# .*\n+/, "");
  // Strip the standard italic meta line ("Lecture notes, …" or "*Companion to…*")
  body = body.replace(/^\*[^*\n]+\*\n+/, "");
  // Strip leading horizontal rule
  body = body.replace(/^---\s*\n+/, "");
  // Strip final italic "*End of …*" footer line
  body = body.replace(/\n*\*End of [^*]+\*\s*$/, "");

  const renderer = new window.marked.Renderer();
  const headings = [];

  renderer.heading = function(text, level) {
    const slug = "h-" + headings.length + "-" + text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
    if (level === 2) {
      // detect numbered section like "1. Units" → split into mark + title
      const m = text.match(/^(\d+)\.\s+(.+)$/);
      const inner = m
        ? `<span class="h2-mark">§ ${m[1].padStart(2, "0")}</span>${m[2]}`
        : text;
      headings.push({ slug, level, text: m ? m[2] : text });
      return `<h2 id="${slug}">${inner}</h2>`;
    }
    if (level === 3) {
      headings.push({ slug, level, text });
      return `<h3 id="${slug}">${text}</h3>`;
    }
    return `<h${level} id="${slug}">${text}</h${level}>`;
  };

  renderer.table = function(header, body) {
    return `<div class="ep-table-wrap"><table><thead>${header}</thead><tbody>${body}</tbody></table></div>`;
  };

  window.marked.setOptions({ renderer, gfm: true, breaks: false, headerIds: false, mangle: false });

  const html = window.marked.parse(body);
  return { html, toc: headings.filter(h => h.level === 2) };
}

/* ============================================================
   HOME VIEW
   ============================================================ */
function EpHome({ go, progress }) {
  const completed = Object.values(progress).filter(Boolean).length;
  const pct = (completed / EP_SESSIONS.length) * 100;
  const nextSession = EP_SESSIONS.find(s => !progress[s.id]) || EP_SESSIONS[0];

  return (
    <div className="ep">
      <div className="ep-bar">
        <div className="ep-bar-left">
          <span className="ep-bar-brand"><span className="ep-bar-dot" />Energy Primer</span>
          <span className="ep-bar-crumb"><span className="ep-bar-sep">·</span><span>Course home</span></span>
        </div>
        <div className="ep-bar-right">
          <span className="ep-bar-prog">
            <span>{completed}/{EP_SESSIONS.length} sessions</span>
            <span className="ep-bar-prog-track"><span className="ep-bar-prog-fill" style={{width: pct + "%"}} /></span>
          </span>
        </div>
      </div>

      <header className="ep-home-hero">
        <div>
          <div className="ep-home-eyebrow">A 20-hour foundation course</div>
          <h1 className="ep-home-title">
            Energy, <em>for advisors</em> to capital, policy, and industry.
          </h1>
          <p className="ep-home-lede">
            The twenty percent of energy knowledge that drives eighty percent of
            advisory outcomes. Built against a commodity trader's blind spots —
            power markets, long-dated capex, infrastructure constraints,
            sectoral pathways, and the geopolitics of minerals.
          </p>
          <button className="ep-home-cta" onClick={() => go("/primer/" + nextSession.id)}>
            <span>{completed === 0 ? "Start the course" : "Continue · session " + nextSession.id}</span>
            <span>→</span>
          </button>
          <a className="ep-home-cta-secondary" href="#/primer/resources/curriculum"
             onClick={(e) => { e.preventDefault(); go("/primer/resources/curriculum"); }}>
            Read the curriculum →
          </a>
        </div>
        <div className="ep-home-meta">
          <div className="ep-home-meta-row">
            <span className="ep-home-meta-lbl">Format</span>
            <span className="ep-home-meta-val">10 sessions<small>~2 hours each · self-paced</small></span>
          </div>
          <div className="ep-home-meta-row">
            <span className="ep-home-meta-lbl">Output</span>
            <span className="ep-home-meta-val">10 deliverables<small>reusable models & frameworks</small></span>
          </div>
          <div className="ep-home-meta-row">
            <span className="ep-home-meta-lbl">Audience</span>
            <span className="ep-home-meta-val">Senior advisors<small>investment, policy, corporate</small></span>
          </div>
        </div>
      </header>

      <section>
        <div className="ep-howto">
          <div className="ep-howto-item">
            <div className="ep-howto-num">01</div>
            <div className="ep-howto-title">Read the lecture notes</div>
            <div className="ep-howto-text">
              Each session opens with the conceptual frame: numbered theory sections,
              key tables, and worked examples.
            </div>
          </div>
          <div className="ep-howto-item">
            <div className="ep-howto-num">02</div>
            <div className="ep-howto-title">Work the case</div>
            <div className="ep-howto-text">
              A real-world case study at the end of every session. Walk through what
              happened and what to generalize.
            </div>
          </div>
          <div className="ep-howto-item">
            <div className="ep-howto-num">03</div>
            <div className="ep-howto-title">Build the deliverable</div>
            <div className="ep-howto-text">
              Each session ships with an exercise — a model, scorecard, or memo
              you can reuse in client work.
            </div>
          </div>
          <div className="ep-howto-item">
            <div className="ep-howto-num">04</div>
            <div className="ep-howto-title">Synthesize</div>
            <div className="ep-howto-text">
              Close with a list of what to internalize. Pre-work for the next
              session keeps the cadence.
            </div>
          </div>
        </div>
      </section>

      <section>
        <div className="ep-home-secthead">
          <h2>The ten sessions</h2>
          <span className="ep-home-secthead-meta">20 hours · 10 deliverables · 10 case studies</span>
        </div>
        <div className="ep-cards">
          {EP_SESSIONS.map((s) => (
            <a key={s.id}
               className={"ep-card " + (progress[s.id] ? "is-done" : "")}
               href={"#/primer/" + s.id}
               onClick={(e) => { e.preventDefault(); go("/primer/" + s.id); }}>
              <div className="ep-card-top">
                <span className="ep-card-num">Session · {s.id}</span>
                <span className={"ep-card-pill " + (progress[s.id] ? "is-done" : "")}>
                  {progress[s.id] ? "✓ Completed" : (s.duration + " min")}
                </span>
              </div>
              <div className="ep-card-title">{s.title}</div>
              <div className="ep-card-sub">{s.subtitle}</div>
              <div className="ep-card-bs">
                <b>Blind spot targeted</b>
                {s.blindSpot}
              </div>
              <div className="ep-card-foot">
                <span>Deliverable · <b>{s.deliverable}</b></span>
                <span>Read →</span>
              </div>
            </a>
          ))}
        </div>
      </section>

      <section>
        <div className="ep-home-secthead">
          <h2>Companion resources</h2>
          <span className="ep-home-secthead-meta">Templates, checklists, and reference</span>
        </div>
        <div className="ep-res">
          {EP_RESOURCES.map((r) => (
            <a key={r.id} className="ep-res-card"
               href={"#/primer/resources/" + r.id}
               onClick={(e) => { e.preventDefault(); go("/primer/resources/" + r.id); }}>
              <span className="ep-res-tag">{r.tag}</span>
              <div className="ep-res-title">{r.title}</div>
              <div className="ep-res-sub">{r.sub}</div>
              <div className="ep-res-foot"><span>Open →</span></div>
            </a>
          ))}
        </div>
      </section>

      <div className="ep-home-footnote">
        Course material is generated and adapted for self-study. Where the
        notes reference institutional sources — IEA, EIA, IRENA, Lazard, BNEF —
        always validate live figures against the primary publications listed
        at the end of each session.
      </div>
    </div>
  );
}

/* ============================================================
   READER VIEW (session OR resource)
   ============================================================ */
function EpReader({ kind, item, go, progress, toggleDone }) {
  // kind: "session" | "resource"
  const [state, setState] = epUse({ html: "", toc: [], loading: true, err: null });
  const [activeHeading, setActiveHeading] = epUse(null);
  const articleRef = epRef(null);

  // load markdown
  epEffect(() => {
    let cancelled = false;
    setState({ html: "", toc: [], loading: true, err: null });
    (async () => {
      try {
        // wait briefly if marked is still loading
        for (let i = 0; i < 30 && !window.marked; i++) {
          await new Promise(r => setTimeout(r, 100));
        }
        const md = await epFetchMd(item.file);
        const { html, toc } = epRenderMarkdown(md);
        if (!cancelled) setState({ html, toc, loading: false, err: null });
      } catch (e) {
        if (!cancelled) setState({ html: "", toc: [], loading: false, err: e.message });
      }
    })();
    return () => { cancelled = true; };
  }, [item.file]);

  // scroll spy for "on this page"
  epEffect(() => {
    if (!state.toc.length) return;
    const handler = () => {
      const headings = state.toc.map(h => document.getElementById(h.slug)).filter(Boolean);
      let active = null;
      for (const h of headings) {
        if (h.getBoundingClientRect().top < 100) active = h.id;
      }
      setActiveHeading(active);
    };
    handler();
    window.addEventListener("scroll", handler, { passive: true });
    return () => window.removeEventListener("scroll", handler);
  }, [state.toc]);

  // scroll to top on new item
  epEffect(() => { window.scrollTo({ top: 0, behavior: "auto" }); }, [item.file]);

  const isSession = kind === "session";
  const idx = isSession ? EP_SESSIONS.findIndex(s => s.id === item.id) : -1;
  const prev = isSession && idx > 0 ? EP_SESSIONS[idx - 1] : null;
  const next = isSession && idx >= 0 && idx < EP_SESSIONS.length - 1 ? EP_SESSIONS[idx + 1] : null;
  const isDone = isSession ? !!progress[item.id] : false;

  return (
    <div className="ep">
      <div className="ep-bar">
        <div className="ep-bar-left">
          <a className="ep-bar-brand" href="#/primer"
             onClick={(e) => { e.preventDefault(); go("/primer"); }}>
            <span className="ep-bar-dot" />Energy Primer
          </a>
          <span className="ep-bar-crumb">
            <span className="ep-bar-sep">/</span>
            <a href="#/primer" onClick={(e) => { e.preventDefault(); go("/primer"); }}>Course</a>
            <span className="ep-bar-sep">/</span>
            <span>{isSession ? ("Session " + item.id) : item.tag}</span>
          </span>
        </div>
        <div className="ep-bar-right">
          {isSession && (
            <span className="ep-bar-prog">
              <span>{idx + 1} of {EP_SESSIONS.length}</span>
              <span className="ep-bar-prog-track">
                <span className="ep-bar-prog-fill" style={{width: (((idx + 1) / EP_SESSIONS.length) * 100) + "%"}} />
              </span>
            </span>
          )}
        </div>
      </div>

      <div className="ep-reader">
        {/* left: course ToC */}
        <aside className="ep-side">
          <div className="ep-side-title">The course</div>
          <ul className="ep-side-list">
            {EP_SESSIONS.map((s) => (
              <li key={s.id}>
                <a className={"ep-side-link " + (isSession && s.id === item.id ? "is-current" : "")}
                   href={"#/primer/" + s.id}
                   onClick={(e) => { e.preventDefault(); go("/primer/" + s.id); }}>
                  <span className="ep-side-num">{s.id}</span>
                  <span className="ep-side-name">{s.title}</span>
                  <span className="ep-side-tick">{progress[s.id] ? "✓" : ""}</span>
                </a>
              </li>
            ))}
          </ul>
          <div className="ep-side-sect">Resources</div>
          <ul className="ep-side-list">
            {EP_RESOURCES.map((r) => (
              <li key={r.id}>
                <a className={"ep-side-link " + (!isSession && r.id === item.id ? "is-current" : "")}
                   href={"#/primer/resources/" + r.id}
                   onClick={(e) => { e.preventDefault(); go("/primer/resources/" + r.id); }}>
                  <span className="ep-side-num">·</span>
                  <span className="ep-side-name">{r.title}</span>
                  <span className="ep-side-tick"></span>
                </a>
              </li>
            ))}
          </ul>
        </aside>

        {/* center: main reader */}
        <article className="ep-main" ref={articleRef}>
          {isSession ? (
            <React.Fragment>
              <div className="ep-eyebrow">Session {item.id} · ~{item.duration} minutes</div>
              <h1 className="ep-h1">{item.title}</h1>
              <p className="ep-main-sub">{item.subtitle}</p>
              <div className="ep-spec">
                <div className="ep-spec-row">
                  <b>Blind spot targeted</b>
                  <span>{item.blindSpot}</span>
                </div>
                <div className="ep-spec-row">
                  <b>Deliverable</b>
                  <span>{item.deliverable}</span>
                </div>
                <div className="ep-spec-row">
                  <b>Concepts</b>
                  <span>{item.concepts.slice(0, 3).join(" · ")}</span>
                </div>
              </div>
            </React.Fragment>
          ) : (
            <React.Fragment>
              <div className="ep-eyebrow">{item.tag}</div>
              <h1 className="ep-h1">{item.title}</h1>
              <p className="ep-main-sub">{item.sub}</p>
            </React.Fragment>
          )}

          {state.loading && (
            <div className="ep-loading">
              Loading lecture notes
              <div className="ep-loading-bar" />
            </div>
          )}
          {state.err && (
            <div className="ep-loading">Could not load this lesson — {state.err}</div>
          )}
          {!state.loading && !state.err && (
            <div className="ep-prose" dangerouslySetInnerHTML={{ __html: state.html }} />
          )}

          {/* prev / next pager for sessions */}
          {isSession && (
            <div className="ep-pager">
              {prev ? (
                <a className="ep-pager-card is-prev"
                   href={"#/primer/" + prev.id}
                   onClick={(e) => { e.preventDefault(); go("/primer/" + prev.id); }}>
                  <span className="ep-pager-lbl">← Previous · {prev.id}</span>
                  <span className="ep-pager-title">{prev.title}</span>
                </a>
              ) : (
                <a className="ep-pager-card ep-pager-empty" href="#/primer"
                   onClick={(e) => { e.preventDefault(); go("/primer"); }}>
                  <span className="ep-pager-lbl">↩ Back</span>
                  <span className="ep-pager-title">Course home</span>
                </a>
              )}
              {next ? (
                <a className="ep-pager-card is-next"
                   href={"#/primer/" + next.id}
                   onClick={(e) => { e.preventDefault(); go("/primer/" + next.id); }}>
                  <span className="ep-pager-lbl">Next · {next.id} →</span>
                  <span className="ep-pager-title">{next.title}</span>
                </a>
              ) : (
                <a className="ep-pager-card is-next ep-pager-empty"
                   href="#/primer/resources/memo-template"
                   onClick={(e) => { e.preventDefault(); go("/primer/resources/memo-template"); }}>
                  <span className="ep-pager-lbl">Wrap up →</span>
                  <span className="ep-pager-title">Client memo template</span>
                </a>
              )}
            </div>
          )}
        </article>

        {/* right: on-this-page */}
        <aside className="ep-onpage">
          <div className="ep-onpage-title">On this page</div>
          <ul className="ep-onpage-list">
            {state.toc.map((h) => (
              <li key={h.slug}>
                <a className={activeHeading === h.slug ? "is-active" : ""}
                   href={"#" + h.slug}
                   onClick={(e) => {
                     e.preventDefault();
                     const el = document.getElementById(h.slug);
                     if (el) window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 16, behavior: "smooth" });
                   }}>
                  {h.text}
                </a>
              </li>
            ))}
          </ul>
          {isSession && (
            <div className="ep-onpage-meta">
              <div>Session · <b>{item.id} / 10</b></div>
              <div>Reading · <b>~{item.duration} min</b></div>
              <div className="ep-onpage-actions">
                <button className={"ep-onpage-btn " + (isDone ? "is-done" : "")} onClick={() => toggleDone(item.id)}>
                  {isDone ? "✓ Completed" : "Mark complete"}
                </button>
              </div>
            </div>
          )}
        </aside>
      </div>
    </div>
  );
}

/* ============================================================
   ROUTER
   ============================================================ */
function EnergyPrimerView() {
  // sub-route after #/primer/...
  const parsePrimer = () => {
    const hash = (window.location.hash || "").replace(/^#\/?/, "");
    const rest = hash.replace(/^energy-primer\/?/, "").replace(/^\/+/, "");
    if (!rest) return { view: "home" };
    if (rest.startsWith("resources/")) {
      const id = rest.slice("resources/".length);
      const r = EP_RESOURCES.find(x => x.id === id);
      if (r) return { view: "resource", item: r };
      return { view: "home" };
    }
    const s = EP_SESSIONS.find(x => x.id === rest);
    if (s) return { view: "session", item: s };
    return { view: "home" };
  };

  const [route, setRoute] = epUse(parsePrimer);
  const [progress, setProgress] = epUse(epLoadProgress);

  epEffect(() => {
    const onHash = () => setRoute(parsePrimer());
    window.addEventListener("hashchange", onHash);
    return () => window.removeEventListener("hashchange", onHash);
  }, []);

  const go = (path) => {
    // path is like "/primer" or "/primer/01" — rewrite to match the app router
    const norm = path.replace(/^\/?primer/, "/energy-primer");
    window.location.hash = norm;
  };
  const toggleDone = (id) => {
    const next = { ...progress, [id]: !progress[id] };
    setProgress(next);
    epSaveProgress(next);
  };

  if (route.view === "home") {
    return <EpHome go={go} progress={progress} />;
  }
  return <EpReader kind={route.view} item={route.item} go={go} progress={progress} toggleDone={toggleDone} />;
}

window.EnergyPrimerView = EnergyPrimerView;
