/* eslint-disable */
/* =============================================================
   app.jsx — Router + shell mount (Spade's Life Explained UI Kit)
   -----
   Browser build: classic <script type="text/babel">; mounts <App/> into #root.

   Two route classes:
     • full-screen flows (auth, onboarding) render WITHOUT the app shell
     • in-app routes render inside Sidebar + Topbar + page-host
   ============================================================= */
(function () {
  const { useState, useEffect } = React;

  const FULLSCREEN = { auth: AuthPage, onboarding: OnboardingPage, admin: AdminPage, join: JoinPage, pending: PendingPage };

  const PAGES = {
    home: HomePage,
    overview: OverviewPage,
    guide: GuidePage,
    centers: CentersPage,
    planets: PlanetsPage,
    gates: GatesPage,
    compare: ComparePage,
    labs: LabsPage,
    settings: SettingsPage,
    notifications: NotificationsPage,
    support: SupportPage,
    report: ReportPage,
    learn: LearnPage,
    create: CreateChartPage,
    charts: MyChartsPage,
    compass: CompassPage,
    dream: DreamPage,
    // detail routes (all handled by the unified DetailPage; read :id from hash)
    gate: DetailPage,
    center: DetailPage,
    channel: DetailPage,
    planet: DetailPage,
    authority: DetailPage,
    profile: DetailPage,
    definition: DetailPage,
    cross: DetailPage,
    notfound: NotFoundPage,
    loading: LoadingChartState,
    error: ErrorState,
    offline: OfflineState,
    feedback: FeedbackDemo,
  };
  // order used for the page-host data-screen-label index (nav order)
  const NAV_ORDER = ["home", "overview", "guide", "centers", "planets", "gates", "compare", "labs"];

  function App() {
    const ROUTE_KEYS = Object.assign({}, PAGES, FULLSCREEN);
    const readHash = () => {
      const head = (window.location.hash || "").replace(/^#\/?/, "").split("/")[0];
      if (!head) return "home";
      const k = ROUTE_KEYS[head] ? head : "notfound";
      // internal routes (labs/compare) are admin-only — silently land home
      return window.SpadeAccess && !SpadeAccess.canSee(k) ? "home" : k;
    };
    const readParam = () => (window.location.hash || "").replace(/^#\/?/, "").split("/")[1] || "";
    const [route, setRouteState] = useState(readHash());
    const [param, setParam] = useState(readParam());
    const [lang, setLang] = useState(() => {
      try { return localStorage.getItem("sle.language") === "en" ? "en" : "ar"; } catch { return "ar"; }
    });
    const [adminCorrection, setAdminCorrection] = useState(false);
    const [adminOwnBirth, setAdminOwnBirth] = useState(false);
    const L = I18N[lang];

    const setRoute = (r) => {
      // r may be a bare key ("overview") or a full path ("gate/64")
      const head = String(r).replace(/^#\/?/, "").split("/")[0];
      const allowed = !(window.SpadeAccess && !SpadeAccess.canSee(head));
      const next = ROUTE_KEYS[head] && allowed ? r : "home";
      const targetHash = `#/${next}`;
      if (window.location.hash !== targetHash) {
        window.location.hash = targetHash;
      }
      setRouteState(ROUTE_KEYS[head] && allowed ? head : "home");
      setParam(String(r).replace(/^#\/?/, "").split("/")[1] || "");
    };

    useEffect(() => {
      const onHash = () => {
        const raw = (window.location.hash || "").replace(/^#\/?/, "").split("/")[0];
        if (window.SpadeAccess && raw && ROUTE_KEYS[raw] && !SpadeAccess.canSee(raw)) { window.location.replace("#/home"); return; }
        setRouteState(readHash()); setParam(readParam());
      };
      window.addEventListener("hashchange", onHash);
      // normalise the URL on first load
      if (!window.location.hash) window.location.replace(`#/${route}`);
      return () => window.removeEventListener("hashchange", onHash);
    }, []);

    useEffect(() => {
      document.documentElement.lang = lang;
      try { localStorage.setItem("sle.language", lang); } catch {}
      document.documentElement.dir = L.dir;
    }, [lang, L.dir]);

    useEffect(() => {
      if (!window.SkyGalaxy) return;
      window.SkyGalaxy.setColor("accent", [180, 160, 255]);
      window.SkyGalaxy.setColor("flare", [248, 198, 72]);
    }, []);

    const cu = window.ChartStore ? ChartStore.currentUser() : null;
    const uname = cu ? (cu.firstName || (cu.email || "").split("@")[0]) : null;
    const user = { name_ar: uname || CHART_SUMMARY.name_ar, name_en: uname || CHART_SUMMARY.name_en };

    const [pkey, setPkey] = useState(0);
    useEffect(() => { setPkey((k) => k + 1); }, [route, param]);

    // re-render the app whenever the active chart (or session) changes
    const [, forceTick] = useState(0);
    useEffect(() => {
      const onChange = () => forceTick((t) => t + 1);
      window.addEventListener("hd-chart-change", onChange);
      return () => window.removeEventListener("hd-chart-change", onChange);
    }, []);

    useEffect(() => {
      if (!ChartStore.remote) return;
      const refresh = () => {
        if (ChartStore.status() !== "approved") return;
        ChartStore.refreshAccessRequests().catch(() => {});
        ChartStore.refreshMemberPermissions?.().catch(() => {});
      };
      window.addEventListener("focus", refresh);
      const timer = setInterval(onTick, 15000);
      function onTick() { forceTick((tick) => tick + 1); }
      return () => { window.removeEventListener("focus", refresh); clearInterval(timer); };
    }, []);

    /* ── سما الميلاد ───────────────────────────────────────────
       تُعرَض مرّة واحدة بعد أول خريطة محسوبة. تُفحَص عند كل تغيّر
       للخريطة لأن المستخدم الجديد يصل بلا خريطة، فتُحسب بعد
       دخوله بيانات ميلاده — لا عند التركيب الأول. */
    const [skyReplay, setSkyReplay] = useState(false);
    const [skySeen, setSkySeen] = useState(null);
    useEffect(() => {
      const replay = () => setSkyReplay(true);
      window.addEventListener("hd-birthsky-replay", replay);
      return () => window.removeEventListener("hd-birthsky-replay", replay);
    }, []);

    /* ── بوّابة الانتظار (نسخة المستخدم فقط) ───────────────────
       قبل القبول لا شيء متاح غير شاشة الانتظار. تُفحَص قبل الراوتر
       كلّه كي لا يفتح رابطٌ مباشر التطبيقَ من خلفها. */
    if (window.SpadeBuild && SpadeBuild.role === "user" && !SpadeBuild.isApproved()) {
      return (
        <div className={`flow-root app-shell ${lang === "ar" ? "rtl" : "ltr"}`} data-lang={lang} dir={L.dir}>
          <PendingPage lang={lang} onRoute={setRoute} onLangToggle={() => setLang(lang === "ar" ? "en" : "ar")} />
        </div>
      );
    }

    const reviewingChart = ChartStore.remote && ChartStore.isAdmin() && ChartStore.hasComputedChart();
    if (ChartStore.remote && ChartStore.isAdmin() && adminOwnBirth) {
      return <main className="flow-root app-shell auth-scroll" data-lang={lang} dir={L.dir}>
        <div className="beta-confirm-tools"><button type="button" className="btn-outline" onClick={() => setAdminOwnBirth(false)}>{lang === "ar" ? "ارجع للإدارة" : "Back to admin"}</button></div>
        <CreateChartPage lang={lang} confirmBirth initialInput={ChartStore.journeyAnswers()?.birth_input} onSaveInput={async (input) => {
          await ChartStore.createChart({ ...input, name: input.name || uname });
          setAdminOwnBirth(false);
          setRoute("overview");
        }} />
      </main>;
    }
    if (ChartStore.remote && ChartStore.status() !== "approved" && !reviewingChart) {
      const status = ChartStore.status();
      const toggle = () => setLang(lang === "ar" ? "en" : "ar");
      const ar = lang === "ar";
      return (
        <div className="flow-root app-shell auth-scroll" data-lang={lang} dir={L.dir}>
          {status === "admin"
            ? <BetaReview lang={lang} onLangToggle={toggle} onConfirmOwnChart={() => setAdminOwnBirth(true)} onOpenChart={(id, edit) => {
                setAdminCorrection(edit); ChartStore.setActiveChart(id); setRoute("overview");
              }} />
            : status === "loading" ? <CosmicLoading lang={lang} />
            : status === "unavailable"
              ? <main className="auth-page auth-centered"><div className="auth-card">
                  <p role="status">{ar ? "الاتصال بالبيتا غير متاح حاليًا." : "The beta service is unavailable."}</p>
                  {status === "unavailable" && <button type="button" className="auth-secondary" onClick={() => location.reload()}>
                    {ar ? "حاول تاني" : "Try again"}
                  </button>}
                </div></main>
              : <AuthPage key={status === "password_recovery" ? "recovery" : "auth"} lang={lang} onRoute={setRoute} onLangToggle={toggle}
                  recovery={status === "password_recovery"} passwordUpdated={status === "password_updated"} />}
        </div>
      );
    }

    if (ChartStore.remote && ChartStore.status() === "approved" && !ChartStore.hasComputedChart()) {
      const name = cu?.firstName || "";
      return <main className="flow-root app-shell auth-scroll" data-lang={lang} dir={L.dir}>
        <div className="beta-confirm-tools">
          <button type="button" className="btn-outline" onClick={() => setLang(lang === "ar" ? "en" : "ar")}>{lang === "ar" ? "English" : "العربية"}</button>
          <button type="button" className="btn-outline" onClick={() => ChartStore.logout()}>{lang === "ar" ? "تسجيل خروج" : "Sign out"}</button>
        </div>
        <CreateChartPage lang={lang} confirmBirth initialInput={ChartStore.journeyAnswers()?.birth_input} onSaveInput={async (input) => {
          await ChartStore.createChart({ ...input, name: input.name || name });
          setRoute("overview");
        }} />
      </main>;
    }

    if (reviewingChart && adminCorrection) {
      const chart = ChartStore.getActiveChart();
      return <main className="flow-root app-shell auth-scroll" data-lang={lang} dir={L.dir}>
        <div className="beta-confirm-tools"><button type="button" className="btn-outline" onClick={() => setAdminCorrection(false)}>{lang === "ar" ? "ارجع للشارت" : "Back to chart"}</button></div>
        <CreateChartPage key={chart.id} lang={lang} param={chart.id} initialInput={chart.input} confirmBirth onSaveInput={async (input) => {
          await ChartStore.updateChart(chart.id, input);
          setAdminCorrection(false);
        }} />
      </main>;
    }

    const skyChartId = ChartStore.getActiveChart()?.id || "local";
    if (skyReplay || (!ChartStore.isAdmin?.() && skySeen !== skyChartId && BirthSkyIntro.shouldShow())) {
      return <BirthSkyIntro lang={lang} replay={skyReplay} onDone={() => {
        setSkySeen(skyChartId);
        setSkyReplay(false);
      }} />;
    }

    // ── full-screen flow (no shell) ──
    if (FULLSCREEN[route]) {
      const Flow = FULLSCREEN[route];
      return (
        <div className={`flow-root ${lang === "ar" ? "rtl" : "ltr"} ${lang === "ar" ? "app-shell rtl" : "app-shell ltr"}`} data-lang={lang} dir={L.dir}>
          <Flow lang={lang} onRoute={setRoute} param={param} onLangToggle={() => setLang(lang === "ar" ? "en" : "ar")} />
        </div>
      );
    }

    // ── in-app route (with shell) ──
    const Page = ChartStore.remote && !BetaAccess.state(route).open ? BetaLocked : PAGES[route] || HomePage;
    const idx = NAV_ORDER.indexOf(route);
    const label = `${String((idx >= 0 ? idx : PAGES[route] ? 90 : 0) + 1).padStart(2, "0")} ${route}`;

    return (
      <React.Fragment>
        <div className={`app-shell ${lang === "ar" ? "rtl" : "ltr"}`} data-lang={lang}>
          <Sidebar lang={lang} route={route} onRoute={setRoute} />
          <div className="main-area">
            <Topbar
              lang={lang}
              user={user}
              onRoute={setRoute}
              onLangToggle={() => setLang(lang === "ar" ? "en" : "ar")}
            />
            <div key={pkey} className="page-host fade-in" data-screen-label={label}>
              {reviewingChart && <div className="beta-confirm-tools">
                <button type="button" className="btn-outline" onClick={() => ChartStore.closeChart()}>{lang === "ar" ? "ارجع للإدارة" : "Back to admin"}</button>
                <button type="button" className="btn-outline" onClick={() => setAdminCorrection(true)}>{lang === "ar" ? "صحّح بيانات الميلاد" : "Correct birth details"}</button>
              </div>}
              <Page lang={lang} onRoute={setRoute} route={route} param={param} onLangToggle={() => setLang(lang === "ar" ? "en" : "ar")} />
            </div>
          </div>
          <MobileNav lang={lang} route={route} onRoute={setRoute} />
        </div>
      </React.Fragment>
    );
  }

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