/* app.jsx — Mounts the whole zine + tweaks panel
 *
 * Three top-level views drive the sub-nav (chapter-nav.jsx):
 *   "about"   — default landing: page header → role tabs → How I lead / hold
 *   "services"— standalone Services page (how we engage / four ways in)
 *   "journey" — the Career story timeline
 */
/* global React, ReactDOM, Cover, AboutZineModal, PageTurn, Offerings, AboutMe, ServicesPage, RolesSection, ROLES, ChapterFoundation, ChapterScale, ChapterEnterprise, ChapterComplexity, ChapterHypergrowth, ChapterDepth, ChapterIndependence, Throughlines, Leadership, Footer, SubNav, CareerJourneyView, TweaksPanel, useTweaks, TweakSection, TweakColor, TweakRadio, TweakSlider */

const { useEffect: useEffectA, useState: useStateA } = React;

/* Chapter ids that, when present in the hash, deep-link into the career-story
   (timeline) view. Kept in one place so the router and CareerJourneyView agree. */
const JOURNEY_CHAPTER_IDS = ["foundation","scale","enterprise","complexity","hypergrowth","depth","independence"];

/* Slugs for the four role deep-links — now on the About me page, e.g.
   "/aworkinglife#/chief-of-staff". Derived from ROLES (data.jsx). */
const ROLE_SLUGS = (typeof ROLES !== "undefined" ? ROLES : []).map((r) => r.slug);

/* Parse the current URL hash into a route:
     #/<role-slug>            → About me, that role's tab active
     #services                → Services page
     #journey / #<chapter-id> → Career story (timeline)
     anything else            → About me (default landing) */
function routeFromHash() {
  const raw = (window.location.hash || "").replace(/^#/, "");
  if (raw.startsWith("/")) {
    const slug = raw.slice(1);
    return { view: "about", roleSlug: ROLE_SLUGS.includes(slug) ? slug : null };
  }
  if (raw === "services") {
    return { view: "services", roleSlug: null };
  }
  if (raw === "journey" || JOURNEY_CHAPTER_IDS.includes(raw)) {
    return { view: "journey", roleSlug: null };
  }
  return { view: "about", roleSlug: null };
}

/* Palettes keyed by name → preview swatches */
const PALETTES = {
  ink:       ["#c5573a", "#1f5d62", "#1a1714", "#f1ead8"],
  riso:      ["#ff4889", "#2c3df0", "#0d0d0d", "#f4f1e4"],
  tabloid:   ["#6e1f23", "#d99c2b", "#1b2e4f", "#ebe3cd"],
  editorial: ["#14392e", "#f0c419", "#0e0e0d", "#ece9df"],
};

function App() {
  const [t, setTweak] = useTweaks(window.__TWEAK_DEFAULTS || { palette: "ink", font: "serif", watercolor: 1.0, distress: 0.35 });

  /* Routing across the three views. Initial route is read from the URL hash so
     every deep link — #/chief-of-staff, #services, #journey, #foundation —
     lands correctly. No hash → About me (default). */
  const initialRoute = routeFromHash();
  const [view, setViewRaw] = useStateA(initialRoute.view);
  const [roleSlug, setRoleSlug] = useStateA(initialRoute.roleSlug);

  /* Navigate to a view, keeping the hash in sync. We use replaceState (not a
     location.hash assignment) so this internal navigation does NOT re-fire our
     own hashchange listener below — state is already being set here. */
  function setView(next) {
    setViewRaw(next);
    if (next === "journey") {
      history.replaceState(null, "", "#journey");
    } else if (next === "services") {
      history.replaceState(null, "", "#services");
      setRoleSlug(null);
    } else {
      /* about (default) — clean URL, default role */
      history.replaceState(null, "", " ");
      setRoleSlug(null);
    }
  }

  /* Select a role tab on the About me page. Single-active: a click activates
     the chosen role's tab. The hash mirrors it so the panel is
     shareable/deep-linkable as #/<slug>. */
  function selectRole(slug) {
    setViewRaw("about");
    setRoleSlug(slug);
    history.replaceState(null, "", `#/${slug}`);
  }

  /* Keep state in sync when the URL hash changes from OUTSIDE our own internal
     navigation — a pasted deep link, or browser back/forward. (replaceState
     calls above don't fire this event, so there's no feedback loop.) */
  useEffectA(() => {
    function onHashChange() {
      const r = routeFromHash();
      setViewRaw(r.view);
      setRoleSlug(r.roleSlug);
    }
    window.addEventListener("hashchange", onHashChange);
    return () => window.removeEventListener("hashchange", onHashChange);
  }, []);

  /* Apply tweaks at document root */
  useEffectA(() => {
    const root = document.documentElement;
    root.setAttribute("data-palette", t.palette);
    root.setAttribute("data-font", t.font);
    root.style.setProperty("--wc-intensity", t.watercolor);
    root.style.setProperty("--distress", t.distress ?? 0.35);
  }, [t.palette, t.font, t.watercolor, t.distress]);

  /* Scroll to top whenever the VIEW changes (toggling between the home and the
     career story). The hash itself is managed by setView/selectRole, so we no
     longer touch it here — otherwise a #/<role> deep link would get wiped on
     first render. Opening a role doesn't change `view`, so it won't scroll. */
  const didMountView = React.useRef(false);
  useEffectA(() => {
    if (!didMountView.current) { didMountView.current = true; return; }
    window.scrollTo({ top: 0, behavior: "instant" in window ? "instant" : "auto" });
  }, [view]);

  /* TweakColor uses array of arrays; we map back to palette name */
  const paletteOptions = Object.entries(PALETTES).map(([name, swatches]) => swatches);
  const currentPaletteArr = PALETTES[t.palette] || PALETTES.ink;
  function onPaletteChange(arr) {
    const name = Object.keys(PALETTES).find((k) =>
      JSON.stringify(PALETTES[k]).toLowerCase() === JSON.stringify(arr).toLowerCase()
    ) || "ink";
    setTweak("palette", name);
  }

  return (
    <>
      <SubNav view={view} setView={setView} />

      {/* "About this zine" easter egg — mounted globally now that the big cover
          no longer leads the Career story page. Opens on first visit + when the
          footer tagline dispatches the event. */}
      {typeof AboutZineModal !== "undefined" && <AboutZineModal />}

      {/* page-host is the filter container for the distress effect — keeping the
          filter off `body` so position:fixed elements (sub-nav, tweaks panel)
          anchor to the viewport instead of being trapped inside a transformed
          containing block. */}
      <div className="page-host">
        {view === "about" ? (
          /* Default landing: page header → role tabs → How I lead / What I hold.
             The 4 roles (deep-linkable via #/<slug>) now live here. */
          <AboutMe activeSlug={roleSlug} onSelectRole={selectRole} />
        ) : view === "services" ? (
          /* Standalone Services page — how we engage / four ways in + CTA. */
          <ServicesPage />
        ) : (
          /* Career story — Cover masthead landing + timeline, inside
             CareerJourneyView. setView powers the Cover supra. */
          <CareerJourneyView setView={setView} />
        )}

        {/* Global footer — colophon + high-five + end-of-issue sign-off.
            Renders on every view so the footer is always present. */}
        <Footer />
      </div>

      <TweaksPanel title="Tweaks">
        <TweakSection label="Palette">
          <TweakColor
            label="Color story"
            value={currentPaletteArr}
            onChange={onPaletteChange}
            options={paletteOptions}
          />
        </TweakSection>

        <TweakSection label="Display font">
          <TweakRadio
            label="Style"
            value={t.font}
            onChange={(v) => setTweak("font", v)}
            options={[
              { value: "serif",     label: "Editorial" },
              { value: "condensed", label: "Condensed" },
              { value: "hand",      label: "Hand" },
            ]}
          />
        </TweakSection>

        <TweakSection label="Watercolor">
          <TweakSlider
            label="Bloom intensity"
            value={Math.round(t.watercolor * 100)}
            min={0}
            max={140}
            step={5}
            unit="%"
            onChange={(v) => setTweak("watercolor", v / 100)}
          />
        </TweakSection>

        <TweakSection label="Distressed (photocopier)">
          <TweakSlider
            label="Zine grit"
            value={Math.round((t.distress ?? 0.35) * 100)}
            min={0}
            max={100}
            step={5}
            unit="%"
            onChange={(v) => setTweak("distress", v / 100)}
          />
        </TweakSection>
      </TweaksPanel>
    </>
  );
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
