/* ============================================================
   App — hash router + shell. Mounts everything.
   ============================================================ */
const { useState: uSapp, useEffect: uEapp, useMemo: uMapp } = React;

function parseHash() {
  let raw = window.location.hash.replace(/^#/, "");
  if (!raw) raw = "/";
  const [path, qs] = raw.split("?");
  const query = {};
  if (qs) qs.split("&").forEach((kv) => {const [k, v] = kv.split("=");if (k) query[decodeURIComponent(k)] = decodeURIComponent(v || "");});
  return { path: path || "/", query };
}

function App() {
  const { db } = useStore();
  const [hash, setHash] = uSapp(parseHash);
  const lastPathRef = React.useRef(parseHash().path);
  const [prevPath, setPrevPath] = uSapp(null);
  const [userId, setUserId] = uSapp(() => {try {return localStorage.getItem("cr_user") || null;} catch (e) {return null;}});
  const [lang, setLangState] = uSapp(() => {try {return localStorage.getItem("cr_lang") || "en";} catch (e) {return "en";}});
  const [edit, setEditState] = uSapp(() => {try {return localStorage.getItem("cr_edit") === "1";} catch (e) {return false;}});
  const [review, setReviewState] = uSapp(() => {try {return localStorage.getItem("cr_review") === "1";} catch (e) {return false;}});
  const [publish, setPublishState] = uSapp(() => {try {return localStorage.getItem("cr_publish") === "1";} catch (e) {return false;}});
  const [tmode, setTmodeState] = uSapp(() => {try {return localStorage.getItem("cr_tester") === "1";} catch (e) {return false;}});

  // resolve the live session user from the store (so role/permission edits apply at once)
  const session = uMapp(() => (db.users || []).find((u) => u.id === userId) || null, [db.users, userId]);
  const role = session ? session.role : null;
  const isAdmin = role === "admin";
  // "auth" keeps its original meaning across the app: a logged-in user who can enter Edit Mode
  const auth = role === "admin" || role === "editor";
  const can = (perm) => roleCan(role, perm);

  uEapp(() => {
    const on = () => {
      setPrevPath(lastPathRef.current);
      const nh = parseHash();
      lastPathRef.current = nh.path;
      setHash(nh);
      window.scrollTo(0, 0);
    };
    window.addEventListener("hashchange", on);
    return () => window.removeEventListener("hashchange", on);
  }, []);

  const go = (path) => {
    const h = "#" + (path.startsWith("/") ? path : "/" + path);
    if (window.location.hash === h) setHash(parseHash());else
    window.location.hash = h;
  };
  const login = (user, stay) => {
    setUserId(user.id);
    try {if (stay) localStorage.setItem("cr_user", user.id);else localStorage.removeItem("cr_user");} catch (e) {}
  };
  const logout = () => {
    setUserId(null);setEditState(false);setReviewState(false);setPublishState(false);setTmodeState(false);
    try {localStorage.removeItem("cr_user");localStorage.removeItem("cr_edit");localStorage.removeItem("cr_review");localStorage.removeItem("cr_publish");localStorage.removeItem("cr_tester");} catch (e) {}
  };
  // back-compat: existing call sites use setAuth(false) to log out
  const setAuth = (v, stay) => {if (!v) logout();};
  const setLang = (l) => {setLangState(l);try {localStorage.setItem("cr_lang", l);} catch (e) {}};
  const clearModes = () => {setReviewState(false);setPublishState(false);setTmodeState(false);try {localStorage.removeItem("cr_review");localStorage.removeItem("cr_publish");localStorage.removeItem("cr_tester");} catch (e) {}};
  const setEdit = (v) => {setEditState(v);if (v) clearModes();try {if (v) {localStorage.setItem("cr_edit", "1");} else localStorage.removeItem("cr_edit");} catch (e) {}};
  const setReview = (v) => {setReviewState(v);if (v) {setEditState(false);setPublishState(false);setTmodeState(false);}try {if (v) {localStorage.setItem("cr_review", "1");localStorage.removeItem("cr_edit");localStorage.removeItem("cr_publish");localStorage.removeItem("cr_tester");} else localStorage.removeItem("cr_review");} catch (e) {}};
  const setPublish = (v) => {setPublishState(v);if (v) {setEditState(false);setReviewState(false);setTmodeState(false);}try {if (v) {localStorage.setItem("cr_publish", "1");localStorage.removeItem("cr_edit");localStorage.removeItem("cr_review");localStorage.removeItem("cr_tester");} else localStorage.removeItem("cr_publish");} catch (e) {}};
  const setTmode = (v) => {setTmodeState(v);if (v) {setEditState(false);setReviewState(false);setPublishState(false);}try {if (v) {localStorage.setItem("cr_tester", "1");localStorage.removeItem("cr_edit");localStorage.removeItem("cr_review");localStorage.removeItem("cr_publish");} else localStorage.removeItem("cr_tester");} catch (e) {}};

  // entering via ?edit=1 deep-link turns edit mode on once
  uEapp(() => {if (hash.query.edit && !edit) setEdit(true);}, [hash.query.edit]);
  // edit mode only exists while authenticated
  uEapp(() => {if (!auth && edit) setEdit(false);}, [auth]);
  // review mode only exists for a logged-in reviewer
  uEapp(() => {if (review && role !== "reviewer") setReviewState(false);}, [role]);
  uEapp(() => {if (publish && role !== "publisher") setPublishState(false);}, [role]);
  uEapp(() => {if (tmode && role !== "tester") setTmodeState(false);}, [role]);

  const { path, query } = hash;
  const reviewMode = role === "reviewer" && review;
  const publishMode = role === "publisher" && publish;
  const testerMode = role === "tester" && tmode;
  // an editor / reviewer / publisher / tester working inside their own restricted mode → show the
  // mode dashboard instead of the public domain pages. Admin keeps editing the real pages.
  const collabHome = role === "editor" && edit || reviewMode || publishMode || testerMode;
  const nav = { route: { path, query }, prevPath, go, auth, setAuth, lang, setLang, edit, setEdit, review, setReview, reviewMode, publish, setPublish, publishMode, tmode, setTmode, testerMode, collabHome, session, role, isAdmin, can, login, logout };
  const editMode = !!(auth && edit);

  // ---- resolve view ----
  let view;
  const segs = path.split("/").filter(Boolean);
  const sectionMatch = db.sections.find((s) => s.route === path);
  const domainMatch = db.domains.find((d) => d.route === path);
  const homeDomain = db.domains.find((d) => d.route === db.profile.defaultRoute) || db.domains[0];
  // two-segment routes: /:section/:ref  and  /:domain/cv
  const seg0Section = segs.length === 2 ? db.sections.find((s) => s.route === "/" + segs[0]) : null;
  const seg0Domain = segs.length === 2 ? db.domains.find((d) => d.route === "/" + segs[0]) : null;

  if (path === "/admin") {
    view = isAdmin ? <Board /> : <AdminLogin />;
  } else if (path === "/board") {
    view = isAdmin ? <Board /> : <AdminLogin />;
  } else if (path === "/contact") {
    view = <ContactPage />;
  } else if (path.startsWith("/shared/")) {
    view = session ? <window.SharedSectionPage sectionId={segs[1]} /> : <DomainPage domain={homeDomain} isHome={true} />;
  } else if (path === "/shared") {
    view = session ? <window.SharedPagesIndex /> : <DomainPage domain={homeDomain} isHome={true} />;
  } else if (path === "/about") {
    view = <AboutMePage />;
  } else if (path === "/feedback") {
    view = <FeedbackPage />;
  } else if (path === "/other") {
    // the "Other" hub is a working surface for editing (admin/editor), reviewing, publishing & testing
    view = editMode || reviewMode || publishMode || testerMode ? <OtherIndex /> : <DomainPage domain={homeDomain} isHome={true} />;
  } else if (path.startsWith("/other/")) {
    view = <OtherPage which={segs[1]} />;
  } else if (segs.length === 2 && segs[1] === "cv" && seg0Domain) {
    view = <CVRequestPage domain={segs[0]} />;
  } else if (segs.length === 2 && seg0Section) {
    view = <ContentDetailPage section={seg0Section} refId={segs[1]} />;
  } else if (path.startsWith("/legal/")) {
    view = <LegalPage which={path.split("/")[2]} />;
  } else if (path === "/" || path === "") {
    view = collabHome ? <window.ModeHome /> : edit && !auth ? <AdminLogin /> : <DomainPage domain={homeDomain} isHome={true} />;
  } else if (sectionMatch) {
    view = <SectionPage section={sectionMatch} />;
  } else if (domainMatch) {
    view = collabHome ? <window.ModeHome /> : edit && !auth ? <AdminLogin /> : <DomainPage domain={domainMatch} isHome={false} />;
  } else {
    view = <DomainPage domain={homeDomain} isHome={true} />;
  }

  const GEB = window.GlobalEditBanner;
  const RFD = window.ReviewFeedbackDock;
  const showBanner = (editMode || reviewMode || publishMode || testerMode) && path !== "/board" && path !== "/admin";
  // logged-in read-only collaborators (reviewer / guest) get a compact feedback dock site-wide
  const showDock = !!session && roleCan(role, "feedback") && path !== "/board" && path !== "/admin";
  return (
    <NavCtx.Provider value={nav}>
      <div className={editMode || reviewMode ? "app-edit" : ""}>
        {showBanner && GEB && <GEB />}
        {view}
        {showDock && RFD && <RFD />}
      </div>
    </NavCtx.Provider>);

}

function Root() {
  const EC = window.EditChromeProvider,FP = window.FeedbackProvider;
  return (
    <StoreProvider>
      <EC>
        <FP>
          <App />
        </FP>
      </EC>
    </StoreProvider>);

}

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