/* SPA router — replaces the old per-page <script>+createRoot bootstrap.
   Each page component is exported on `window` from its IIFE-wrapped source
   file (HomeApp, PlatformApp, …). The router mounts ONE React tree, swaps
   only the page subtree on navigation, and keeps Nav persistent so the
   header doesn't flash between routes. */

const { useState, useEffect, useRef } = React;

const ROUTES = [
  { path:"/",                page:"HomeApp",         key:"home",         darkOnTop:true,  title:"VivaMed BioPharma — Precision drug repurposing" },
  { path:"/platform",        page:"PlatformApp",     key:"platform",     darkOnTop:true,  title:"Platform — VivaMed BioPharma" },
  { path:"/pipeline",        page:"PipelineApp",     key:"pipeline",     darkOnTop:true,  title:"Pipeline — VivaMed BioPharma" },
  { path:"/partnerships",    page:"PartnershipsApp", key:"partnerships", darkOnTop:true,  title:"Partnerships — VivaMed BioPharma" },
  { path:"/people",          page:"PeopleApp",       key:"people",       darkOnTop:false, title:"Team & Advisors — VivaMed BioPharma" },
  { path:"/advisors",        page:"AdvisorsApp",     key:"people",       darkOnTop:true,  title:"Clinical Advisory Board — VivaMed BioPharma" },
  { path:"/contact",         page:"ContactApp",      key:"contact",      darkOnTop:false, title:"Contact — VivaMed BioPharma" },
  { path:"/investors",       page:"InvestorsApp",    key:"investors",    darkOnTop:false, title:"Investors — VivaMed BioPharma" },
  { path:"/blog",            page:"BlogApp",         key:"blog",         darkOnTop:false, title:"Blog — VivaMed BioPharma" },
  { path:"/privacy-policy",  page:"PrivacyApp",      key:"privacy",      darkOnTop:false, title:"Privacy Policy — VivaMed BioPharma" },
  { path:"/terms-of-use",    page:"TermsApp",        key:"terms",        darkOnTop:false, title:"Terms of Use — VivaMed BioPharma" },
];

const FADE_MS = 220;

function normalizePath(path){
  if (!path || path === "/") return "/";
  let p = path.replace(/\/index\.html$/i, "/").replace(/\.html$/i, "");
  if (p.length > 1 && p.endsWith("/")) p = p.slice(0, -1);
  return p;
}

function findRoute(path){
  const n = normalizePath(path);
  return ROUTES.find(r => r.path === n) || null;
}

function isInternalNavClick(e){
  if (e.defaultPrevented) return null;
  if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return null;
  if (e.button !== 0) return null;
  const a = e.target.closest && e.target.closest("a[href]");
  if (!a) return null;
  if (a.target && a.target !== "" && a.target !== "_self") return null;
  if (a.hasAttribute("download")) return null;
  const url = new URL(a.getAttribute("href"), location.href);
  if (url.origin !== location.origin) return null;
  // Only intercept paths we know how to render
  if (!findRoute(url.pathname)) return null;
  return url;
}

/* Wrap a state update in a same-doc View Transition when supported, so the
   browser keeps a snapshot of the OLD DOM on screen while the new tree
   mounts — avoids the white-flash that appears when React unmounts the
   old subtree before the new one paints.  Falls back to a plain update
   on browsers without the API. */
function withViewTransition(updater){
  if (typeof document !== "undefined"
      && typeof document.startViewTransition === "function"
      && ReactDOM && typeof ReactDOM.flushSync === "function") {
    document.startViewTransition(() => ReactDOM.flushSync(updater));
  } else {
    updater();
  }
}

function Router(){
  const [path, setPath] = useState(() => normalizePath(location.pathname));
  const [search, setSearch] = useState(() => location.search);

  // Click interceptor — own all internal-link clicks anywhere in the doc.
  useEffect(() => {
    function onClick(e){
      const url = isInternalNavClick(e);
      if (!url) return;
      e.preventDefault();
      navigate(url.pathname + url.search + url.hash);
    }
    document.addEventListener("click", onClick);
    return () => document.removeEventListener("click", onClick);
  }, []);

  // Back/forward.
  useEffect(() => {
    function onPop(){
      withViewTransition(() => {
        setPath(normalizePath(location.pathname));
        setSearch(location.search);
      });
    }
    window.addEventListener("popstate", onPop);
    return () => window.removeEventListener("popstate", onPop);
  }, []);

  // Title sync per route.
  useEffect(() => {
    const r = findRoute(path);
    if (r) document.title = r.title;
  }, [path]);

  function navigate(target){
    const url = new URL(target, location.href);
    const newPath = normalizePath(url.pathname);
    const newSearch = url.search;
    // Compare against live location, not closure-captured state — the click
    // handler is registered once via useEffect([]) and otherwise holds the
    // initial render's path value, so a "Home from another page" click would
    // see path==="/" and short-circuit. location.pathname is always current.
    const currentPath = normalizePath(location.pathname);
    const currentSearch = location.search;
    if (newPath === currentPath && newSearch === currentSearch && !url.hash) return;

    history.pushState({}, "", url.pathname + url.search + url.hash);

    if (newPath === currentPath && newSearch === currentSearch && url.hash) {
      // same page anchor — let browser scroll
      const el = document.getElementById(url.hash.slice(1));
      if (el) el.scrollIntoView({ behavior:"smooth", block:"start" });
      return;
    }

    withViewTransition(() => {
      setPath(newPath);
      setSearch(newSearch);
    });

    // After the swap, ask the tile-reveal observer to pick up any new tiles in
    // the freshly-mounted route subtree (MutationObserver normally handles
    // this, but a direct nudge avoids any timing edge cases).
    setTimeout(() => { if (typeof window.__vmTileScan === "function") window.__vmTileScan(); }, 0);

    if (url.hash) {
      // give React a tick, then scroll to anchor
      setTimeout(() => {
        const el = document.getElementById(url.hash.slice(1));
        if (el) el.scrollIntoView({ behavior:"auto", block:"start" });
        else window.scrollTo(0, 0);
      }, 0);
    } else {
      window.scrollTo(0, 0);
    }
  }

  const route = findRoute(path) || ROUTES[0];
  const Page = window[route.page];

  if (!Page) {
    return (
      <main style={{padding:"120px 32px", textAlign:"center", color:"#6E8297", fontFamily:"Inter,system-ui"}}>
        <p style={{fontSize:14, fontFamily:"IBM Plex Mono, monospace"}}>Loading…</p>
      </main>
    );
  }

  return (
    <>
      <Nav active={route.key} darkOnTop={route.darkOnTop}/>
      <div className="route-frame" key={route.path + search}>
        <Page/>
      </div>
      <BackToTop/>
    </>
  );
}

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