// app.jsx — multi-tab router. Renders the site full-screen.

// Tabs that have a dedicated public page (mirrors the nav strip in shell.jsx).
// Used to map URL hash routes like "#transmissions" → tab="transmissions".
const TAB_ROUTES = ["home", "about", "mythology", "transmissions", "playlists", "inbox", "creator"];

// Combine hash + pathname into a single canonical "/route" string.
// Hash wins over pathname so `/#admin` works on hosts that 404 on /admin.
function readRoute() {
  if (typeof window === "undefined") return "/";
  const rawHash = (window.location.hash || "").replace(/^#\/?/, "/");
  if (rawHash !== "/" && rawHash !== "") return rawHash;
  return window.location.pathname || "/";
}

// First segment of the route. "/transmissions" → "transmissions"; "/" → ""
function firstSegment(route) {
  return route.replace(/^\//, "").split("/")[0];
}

function tabFromRoute(route) {
  const seg = firstSegment(route);
  return TAB_ROUTES.includes(seg) ? seg : null;
}

function App() {
  const theme = "cobalt";
  const { isMobile } = (window.useViewport ? window.useViewport() : { isMobile: false });
  if (window.__themeName !== theme) window.__setTheme(theme);

  // Parse a route string into a tab + optional myth slug.
  // /mythology/<slug> is a real path so press can share song-specific URLs that
  // unfurl with myth-specific meta + JSON-LD via the Cloudflare Worker.
  const mythSlugFromRoute = (r) => {
    const m = r.match(/^\/mythology\/([\w-]+)\/?$/);
    return m ? m[1] : null;
  };

  const [route, setRoute] = React.useState(() => readRoute());
  const [tab, setTab] = React.useState(() => tabFromRoute(readRoute()) || "home");
  const [mythOpen, setMythOpen] = React.useState(() => mythSlugFromRoute(readRoute()));

  React.useEffect(() => {
    const onChange = () => {
      const r = readRoute();
      setRoute(r);
      const t = tabFromRoute(r);
      if (t) setTab(t);
      setMythOpen(mythSlugFromRoute(r));
    };
    window.addEventListener("hashchange", onChange);
    window.addEventListener("popstate", onChange);
    return () => {
      window.removeEventListener("hashchange", onChange);
      window.removeEventListener("popstate", onChange);
    };
  }, []);

  const listenSlug = route.startsWith("/listen/")
    ? route.slice("/listen/".length).replace(/\/+$/, "")
    : "grain-beneath-the-blue";

  // Navigate to a tab AND update the URL. Resets the pathname to "/" when
  // leaving a deep path (/mythology/<slug>, /listen/<slug>) so the URL bar
  // doesn't get stuck on the previous song's slug after the user clicks away.
  const navigateTab = (newTab) => {
    setTab(newTab);
    setMythOpen(null);
    const targetHash = newTab === "home" ? "" : `#${newTab}`;
    const onDeepPath = /^\/(mythology|listen)\//.test(window.location.pathname);
    const basePath = onDeepPath ? "/" : window.location.pathname;
    const url = basePath + window.location.search + targetHash;
    if (url !== window.location.pathname + window.location.search + window.location.hash) {
      window.history.pushState({}, "", url);
      setRoute(readRoute());
    }
  };

  // Drive URL when MythologyPage opens/closes a song detail.
  // Open  → /mythology/<slug> (path-based, shareable with custom unfurl)
  // Close → /mythology         (gallery)
  const setMythSlug = (slug) => {
    setMythOpen(slug);
    const newPath = slug ? `/mythology/${slug}` : "/mythology";
    if (window.location.pathname !== newPath || window.location.hash) {
      window.history.pushState({}, "", newPath + window.location.search);
      setRoute(readRoute());
    }
  };

  const goToMythology = (slug) => {
    setTab("mythology");
    setMythSlug(slug || null);
  };
  const goHome = () => {
    setMythOpen(null);
    setTab("home");
    // Force the URL back to "/" — without this, when on /listen/<slug> or
    // /mythology/<slug>, pushing the same pathname keeps the route matcher
    // rendering the listen/mythology page even though state says "home".
    window.history.pushState({}, "", "/");
    setRoute(readRoute());
  };

  // /listen/<slug> (or /#listen/<slug>) renders the smart-link page full-screen.
  // On mobile we use the mobile-first variant baked into listen.jsx.
  if (route.startsWith("/listen")) {
    const wrap = isMobile
      ? { position: "relative", minHeight: "100dvh", background: "#000" }
      : { position: "fixed", inset: 0, overflow: "auto", background: "#000" };
    return (
      <div style={wrap}>
        {isMobile
          ? <ListenPageMobile slug={listenSlug} onMythologyClick={goToMythology} onHomeClick={goHome} />
          : <ListenPage       slug={listenSlug} onMythologyClick={goToMythology} onHomeClick={goHome} />}
      </div>
    );
  }

  // /admin (or /#admin) — Spotify import workflow. Password-gated inside AdminPage.
  if (route.startsWith("/admin")) {
    const wrap = isMobile
      ? { position: "relative", minHeight: "100dvh", background: "#02030a" }
      : { position: "fixed", inset: 0, overflow: "auto", background: "#02030a" };
    return (
      <div style={wrap}>
        <AdminPage />
      </div>
    );
  }

  let page;
  if (tab === "home") page = <HomeIndustrial tab={tab} onTabChange={navigateTab} />;
  else if (tab === "about") page = <AboutPage tab={tab} onTabChange={navigateTab} />;
  else if (tab === "mythology") page = <MythologyPage tab={tab} onTabChange={navigateTab} initialOpen={mythOpen} onOpenChange={setMythSlug} />;
  else if (tab === "transmissions") page = <TransmissionsPage tab={tab} onTabChange={navigateTab} />;
  else if (tab === "playlists") page = <PlaylistsPage tab={tab} onTabChange={navigateTab} />;
  else if (tab === "inbox") page = <InboxPage tab={tab} onTabChange={navigateTab} />;
  else if (tab === "creator") page = <SculptorPage tab={tab} onTabChange={navigateTab} />;
  else page = <Stub tab={tab} onTabChange={navigateTab} />;

  const appWrap = isMobile
    ? { position: "relative", minHeight: "100dvh", background: "#02030a" }
    : { position: "fixed", inset: 0, overflow: "hidden", background: "#02030a" };
  return (
    <div style={appWrap}>
      {/* SiteOverlay is mounted inside Shell (after the radial-gradient backdrop)
          so it stacks above the dark bg but below content. Re-mounting on tab
          switch is cheap because the config fetch is cached by diavalCachedFetch. */}
      {page}
    </div>
  );
}

function Stub({ tab, onTabChange }) {
  const S = window.shellStyles;
  return (
    <Shell tab={tab} onTabChange={onTabChange} page="—">
      <div style={{ position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", flexDirection: "column", gap: 18 }}>
        <div style={{ fontSize: 13, color: S.bloodHot, letterSpacing: "0.4em" }}>// {tab.toUpperCase()}</div>
        <div style={{ fontFamily: S.display, fontSize: 80, color: S.bone, letterSpacing: "-0.02em" }}>UNDER CONSTRUCTION</div>
        <div style={{ fontSize: 12, color: S.ash, letterSpacing: "0.25em" }}>this transmission has not yet been written.</div>
      </div>
    </Shell>
  );
}

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