// ============================================================
// site-shell.jsx
// Shared site chrome for every page (landing, wiki, forum).
// Owns: theme (localStorage, cross-page), DM mode (sessionStorage),
// top-nav, footer, password modal, the moon DM toggle.
//
// Every page renders:
//   <SiteShell current="story">
//     ...page content...
//   </SiteShell>
// ============================================================

const SS_THEME_KEY = "hc:theme";
const SS_DM_KEY    = "hc:dm";

// ---- Section catalog: drives nav order + section-card metadata ----
const SECTIONS = [
  {
    id: "story",   label: "Story",   href: "wiki/story.html",
    blurb: "Where the party stands after the First Tax: Corvin, the Alberich Clan, the Greenward, and the first gold thread.",
    glyph: "I",
  },
  {
    id: "world",   label: "World",   href: "wiki/world.html",
    blurb: "Thoria: old roads, older roots, and a seal weakening beneath ordinary towns.",
    glyph: "II",
  },
  {
    id: "company", label: "Company", href: "wiki/company.html",
    blurb: "The player characters: sheets, hooks, public stories, and DM-only wounds.",
    glyph: "III",
  },
  {
    id: "cast",    label: "Cast",    href: "wiki/cast.html",
    blurb: "Aldenmire locals, enemies, witnesses, and everyone else making this worse.",
    glyph: "IV",
  },
  {
    id: "codex",   label: "Codex",   href: "wiki/codex.html",
    blurb: "Factions, bestiary, artifacts, session log, and the rules of the table. The reference shelf.",
    glyph: "V",
  },
  {
    id: "forum",   label: "Forum",   href: "forum.html",
    blurb: "Where the table talks between sessions. Recaps, theories, the occasional rules argument.",
    glyph: "✦",
  },
];

window.SS_SECTIONS = SECTIONS;

// ---- Theme + DM hooks ----
function useTheme() {
  const initial = React.useMemo(() => {
    try { return localStorage.getItem(SS_THEME_KEY) || (window.TWEAKS_DEFAULTS && window.TWEAKS_DEFAULTS.theme) || "day"; }
    catch (e) { return "day"; }
  }, []);
  const [theme, setThemeState] = React.useState(initial);

  React.useEffect(() => {
    if (theme === "night") document.documentElement.setAttribute("data-theme", "night");
    else document.documentElement.removeAttribute("data-theme");
    try { localStorage.setItem(SS_THEME_KEY, theme); } catch (e) {}
  }, [theme]);

  // Cross-page sync: when another tab/page changes theme, follow.
  React.useEffect(() => {
    const onStorage = (e) => {
      if (e.key === SS_THEME_KEY && e.newValue && e.newValue !== theme) setThemeState(e.newValue);
    };
    window.addEventListener("storage", onStorage);
    return () => window.removeEventListener("storage", onStorage);
  }, [theme]);

  return [theme, setThemeState];
}

function useDmModeState() {
  const [dm, setDm] = React.useState(() => {
    try { return sessionStorage.getItem(SS_DM_KEY) === "1"; } catch (e) { return false; }
  });
  React.useEffect(() => {
    document.body.classList.toggle("dm-mode", dm);
    try { sessionStorage.setItem(SS_DM_KEY, dm ? "1" : "0"); } catch (e) {}
  }, [dm]);
  return [dm, setDm];
}

// ---- Top nav ----
function SiteNav({ current, theme, setTheme, basePath = "" }) {
  const [scrolled, setScrolled] = React.useState(false);
  React.useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 60);
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  const homeHref = basePath ? basePath + "index.html" : "index.html";

  return (
    <nav className={"topnav" + (scrolled ? " scrolled" : "")}>
      <a className="topnav-brand" href={homeHref}>
        <span className="redacted-title">[REDACTED]</span>
      </a>
      <div className="topnav-links">
        {SECTIONS.map((s) => (
          <a
            key={s.id}
            className={"topnav-link" + (current === s.id ? " active" : "")}
            href={basePath + s.href}
          >
            {s.label}
          </a>
        ))}
        <button
          className="theme-toggle"
          onClick={() => setTheme(theme === "night" ? "day" : "night")}
          aria-label="Toggle theme"
          title={theme === "night" ? "Switch to day · green magic" : "Switch to night · blood red"}
        >
          <span className={"theme-toggle-glyph " + (theme === "night" ? "is-night" : "is-day")}></span>
          <span className="theme-toggle-label">{theme === "night" ? "Night" : "Day"}</span>
        </button>
      </div>
    </nav>
  );
}

// ---- Footer ----
function SiteFooter() {
  return (
    <footer className="footer">
      <div className="footer-glyph">✦ · ✦ · ✦</div>
      <div className="footer-title" style={{marginTop: 18}}><span className="redacted-title">[REDACTED]</span></div>
      <div className="footer-sub">A campaign in Thoria · Player ledger</div>
      <div style={{fontFamily:"var(--font-display)", fontStyle:"italic", color:"var(--text-dim)", fontSize: 15, maxWidth: 480, margin: "0 auto"}}>
        "The roots spiral downward. Deliberately."
      </div>
    </footer>
  );
}

// ---- Page header strip (for wiki + forum pages) ----
function PageHeader({ chapterNum, eyebrow, title, deck, crumb, basePath = "" }) {
  return (
    <header className="page-header">
      <div className="page-header-inner">
        <nav className="breadcrumb">
          <a href={basePath + "index.html"}>Thoria Campaign</a>
          <span className="crumb-sep">›</span>
          <span className="crumb-current">{crumb}</span>
        </nav>
        {chapterNum && <div className="page-header-chapter">Section {chapterNum}</div>}
        {eyebrow && <div className="page-header-eyebrow">{eyebrow}</div>}
        <h1 className="page-header-title" dangerouslySetInnerHTML={{__html: title}}></h1>
        {deck && <p className="page-header-deck">{deck}</p>}
      </div>
    </header>
  );
}

// ---- DM moon toggle + DM banner + password modal (all-in-one) ----
function DMShell({ children }) {
  const [dm, setDm] = useDmModeState();
  const [showPwd, setShowPwd] = React.useState(false);
  const expected = (window.TWEAKS_DEFAULTS && window.TWEAKS_DEFAULTS.dmPassword) || "secret-moon";

  const handleMoonClick = () => {
    if (dm) setDm(false);
    else setShowPwd(true);
  };

  return (
    <DMContext.Provider value={dm}>
      {dm && (
        <div className="dm-banner">
          <span>◐ DM View — secrets visible · inline editing on</span>
          <button className="dm-banner-exit" onClick={() => setDm(false)}>Return to player view</button>
        </div>
      )}
      {children}
      <button
        className="moon-toggle"
        onClick={handleMoonClick}
        title={dm ? "Return to player view" : ""}
        aria-label="Toggle DM view"
      ></button>
      {showPwd && (
        <PasswordModal
          expected={expected}
          onClose={() => setShowPwd(false)}
          onSubmit={() => { setDm(true); setShowPwd(false); }}
        />
      )}
    </DMContext.Provider>
  );
}

// ---- The whole shell: theme + nav + DM + footer wrapper ----
function SiteShell({ current, basePath = "", children }) {
  const [theme, setTheme] = useTheme();
  return (
    <DMShell>
      <SiteNav current={current} theme={theme} setTheme={setTheme} basePath={basePath} />
      {children}
      <SiteFooter />
    </DMShell>
  );
}

Object.assign(window, { SECTIONS, useTheme, useDmModeState, SiteNav, SiteFooter, PageHeader, DMShell, SiteShell });
