/* ========================================================================
   roles-main.jsx — App root: role-aware router, guards, tweaks
   ======================================================================== */
const { useState: uM2, useEffect: eM2 } = React;

function requiredCap(path) {
  const caps = window.ROUTE_CAPS;
  if (caps[path]) return caps[path];
  const hit = Object.keys(caps).find((k) => path === k || path.startsWith(k + "/"));
  return hit ? caps[hit] : null;
}

function RoleApp({ tweaks: t }) {
  const ctx = useRoles();
  if (window.MP_SSO) window.MP_SSO.useSso();
  window.MP_TWEAKS = t;
  window.MP_TOAST = ctx.toast;
  /* Demo popover — appears near the button that was clicked */
  window.DEMO_TOAST = (msg, e) => {
    const el = document.createElement("div");
    el.className = "mp-demo-pop";
    el.innerHTML = '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg><div><div class="mp-demo-pop-label">Functionality not available in this demo</div><div class="mp-demo-pop-body">' + msg + '</div></div>';
    document.body.appendChild(el);
    const btn = e && e.currentTarget;
    if (btn) {
      const r = btn.getBoundingClientRect();
      const pw = el.offsetWidth, ph = el.offsetHeight;
      let top = r.bottom + 8, left = r.left + r.width / 2 - pw / 2;
      if (top + ph > window.innerHeight - 12) top = r.top - ph - 8;
      if (left < 8) left = 8;
      if (left + pw > window.innerWidth - 8) left = window.innerWidth - pw - 8;
      el.style.top = top + "px"; el.style.left = left + "px";
    } else { el.style.top = "50%"; el.style.left = "50%"; el.style.transform = "translate(-50%,-50%)"; }
    setTimeout(() => { if (el.parentNode) el.remove(); }, 2600);
  };
  const route = useRoute();
  const path = route.path;
  const parts = route.parts;

  eM2(() => { if (window.lucide) { try { window.lucide.createIcons(); } catch (e) {} } });
  eM2(() => { document.body.classList.toggle("is-density-compact", t.density === "compact"); }, [t.density]);
  eM2(() => { document.body.classList.toggle("is-row-zebra", t.row_style === "zebra"); }, [t.row_style]);
  eM2(() => {
    document.body.className = document.body.className.replace(/\bmp-role-\w+/g, "").trim() + " mp-role-" + ctx.role;
  }, [ctx.role]);

  if (ctx.signedOut) return <SignedOutScreen />;

  /* Screens that sit outside the signed-in shell (design delta §5) */
  if (parts[0] === "accept-invitation") return <AcceptInvitationScreen state={parts[1] || "new"} />;
  if (parts[0] === "confirm-email") return <ConfirmEmailScreen state={parts[1] || "success"} />;
  if (parts[0] === "signin") return <SignInScreen />;

  const cap = requiredCap(path);
  const denied = cap && !ctx.can(cap);

  let page;
  if (denied) page = <PermissionDeniedPage />;
  else if (path === "/dashboard" || path === "/") page = <DashboardPage tweaks={t} />;
  else if (path === "/sims") page = <SimsIndexPage tweaks={t} />;
  else if (path === "/sims/travel/new") page = <window.TravelBuyPage tweaks={t} />;
  else if (path === "/support/tickets") page = <window.SupportTicketsPage />;
  else if (path === "/support/tickets/new") page = <window.SupportTicketFormPage />;
  else if (parts[0] === "support" && parts[1] === "tickets" && parts[3] === "edit") page = <window.SupportTicketFormPage id={parts[2]} />;
  else if (parts[0] === "support" && parts[1] === "tickets" && parts[2]) page = <window.SupportTicketShowPage id={parts[2]} />;
  else if (path === "/sims/assign-csv") page = <window.AssignFromCsvPage />;
  else if (path === "/users/import") page = <window.ImportUsersPage />;
  else if (parts[0] === "sims" && parts[2] === "transfer") page = <window.TransferNumberPage id={parts[1]} />;
  else if (parts[0] === "sims" && parts[2] === "edit") page = <SimEditPage id={parts[1]} />;
  else if (parts[0] === "sims" && parts[1]) page = <SimShowPage id={parts[1]} />;
  else if (path === "/users") page = <UsersIndexPage />;
  else if (path === "/users/new") page = <UserNewPage />;
  else if (parts[0] === "users" && parts[2] === "assign-sim") page = window.AssignSimPage ? <window.AssignSimPage userId={parts[1]} /> : null;
  else if (parts[0] === "users" && parts[2] === "edit") page = <UserEditPage id={parts[1]} />;
  else if (parts[0] === "users" && parts[1]) page = <UserShowPage id={parts[1]} />;
  else if (path === "/rules") page = <RulesPage />;
  else if (path === "/alerts") page = <AlertsPage />;
  else if (path === "/co2") page = <Co2Page />;
  else if (path === "/subscriptions") page = <SubscriptionsIndexPage />;
  else if (parts[0] === "subscriptions" && parts[2] === "upgrade") page = <SubscriptionUpgradePage id={parts[1]} selectedSerial={parts[3]} />;
  else if (parts[0] === "subscriptions" && parts[1]) page = <SubscriptionShowPage id={parts[1]} />;
  else if (path === "/support") page = <SupportPage />;
  else if (parts[0] === "settings") page = <RoleSettingsPage sub={parts[1] || "profile"} />;
  else page = <DashboardPage tweaks={t} />;

  return (
    <div className="mp-app">
      <RoleSidebar activePath={path} />
      <div className="mp-main">
        <main className="mp-content">{page}</main>
      </div>
      <ToastStack />
    </div>
  );
}

function App() {
  const [t, setTweak] = window.useTweaks ? window.useTweaks(window.TWEAK_DEFAULTS_ROLES) : [window.TWEAK_DEFAULTS_ROLES, () => {}];
  if (window.MP_SSO) window.MP_SSO.useSso();
  return (
    <RolesProvider failMode={t.fail_mode === "none" ? null : t.fail_mode}>
      <RoleApp tweaks={t} />
      {window.TweaksPanel && window.MP_DEMO && window.MP_DEMO.isPresenter() ? (
        <TweaksPanel title="Demo">
          <TweakSection label="Reset">
            <TweakButton label="Reset Demo" onClick={() => {
              if (window.confirm("Reset the demo? Every request, purchase, batch, install and setting goes back to the seeded estate.")) window.MP_DEMO.resetDemo();
            }} />
          </TweakSection>

          <TweakSection label="Data pool">
            <TweakSelect label="Pool usage" value={t.pool_usage_demo}
              options={[
                { value: "live", label: "As seeded" },
                { value: "85", label: "85%" },
                { value: "90", label: "90%" },
                { value: "97", label: "97%" },
                { value: "100", label: "100%, blocked" }]}
              onChange={(v) => setTweak("pool_usage_demo", v)} />
          </TweakSection>

          <TweakSection label="Requests and usage">
            <TweakButton label="Complete the open request" onClick={() => { if (!window.MP_REQ.resolveNewestOpen("completed")) window.alert("No open request. Send one from an international SIM first."); }} />
            <TweakButton label="Decline the open request" onClick={() => { if (!window.MP_REQ.resolveNewestOpen("declined")) window.alert("No open request. Send one from an international SIM first."); }} />
            <TweakButton label="Roll usage month forward" onClick={() => window.MP_REQ.rollUsageMonth()} />
          </TweakSection>

          <TweakSection label="eSIM and travel">
            <TweakButton label="Confirm install on the first ready eSIM" onClick={() => { if (!window.MP_ESIM.confirmFirstReady()) window.alert("Every eSIM is already installed."); }} />
            <TweakButton label="Simulate first data on a waiting plan" onClick={() => { if (!window.MP_TRAVEL.simulateFirstUse((window.MP_TRAVEL.firstAwaitingPlan() || {}).id)) window.alert("No plan is waiting for its first use."); }} />
            <TweakButton label="Set the next plan to end in five days" onClick={() => { if (!window.MP_TRAVEL.setExpiringSoon()) window.alert("No active one-off plan to bring forward."); }} />
            <TweakSelect label="Buying a travel plan" value={t.travel_purchase}
              options={[{ value: "works", label: "Succeeds" }, { value: "fails", label: "Fails at the supplier" }]}
              onChange={(v) => setTweak("travel_purchase", v)} />
          </TweakSection>

          <TweakSection label="Bulk and batches">
            <TweakRadio label="Bulk actions" value={t.bulk_fail}
              options={[{ value: "none", label: "All succeed" }, { value: "some", label: "Fail a subset" }]}
              onChange={(v) => setTweak("bulk_fail", v)} />
            <TweakButton label="Fulfil the open batch" onClick={() => {
              const b = window.MP_BATCH.firstOpenBatch();
              if (!b) { window.alert("No batch is waiting to be fulfilled."); return; }
              window.MP_BATCH.fulfilBatch(b.id, t.batch_fail === "two" ? 2 : 0);
            }} />
            <TweakRadio label="Fulfilling a batch" value={t.batch_fail}
              options={[{ value: "none", label: "All rows succeed" }, { value: "two", label: "Fail 2 rows" }]}
              onChange={(v) => setTweak("batch_fail", v)} />
          </TweakSection>

          <TweakSection label="Single sign-on">
            <TweakSelect label="Single sign-on"
              value={window.MP_SSO ? (window.MP_SSO.state === "active" ? window.MP_SSO.enforcement : window.MP_SSO.state) : "off"}
              options={[
                { value: "off", label: "Not configured" },
                { value: "setup", label: "Setup in progress" },
                { value: "optional", label: "Active, optional" },
                { value: "required", label: "Active, required" },
                { value: "attention", label: "Needs attention" }]}
              onChange={(v) => window.MP_SSO.setSsoState(v)} />
            <TweakButton label="Complete SSO setup" onClick={() => {
              if (!window.MP_SSO.completeSetup()) window.alert("Start a setup handoff first.");
            }} />
          </TweakSection>

          <TweakSection label="Out-of-app screens">
            <TweakButton label="Invitation: set password" onClick={() => { window.location.hash = "/accept-invitation/new"; }} />
            <TweakButton label="Invitation: expired" onClick={() => { window.location.hash = "/accept-invitation/expired"; }} />
            <TweakButton label="Invitation: already accepted" onClick={() => { window.location.hash = "/accept-invitation/accepted"; }} />
            <TweakButton label="Email change: confirmed" onClick={() => { window.location.hash = "/confirm-email/success"; }} />
            <TweakButton label="Email change: expired" onClick={() => { window.location.hash = "/confirm-email/expired"; }} />
            <TweakButton label="Sign in screen" onClick={() => { window.location.hash = "/signin"; }} />
          </TweakSection>

          <TweakSection label="Prototype">
            <TweakSelect label="Next action fails" value={t.fail_mode}
              options={[
                { value: "none", label: "Nothing fails" },
                { value: "invite", label: "Sending an invitation" },
                { value: "role", label: "Changing a role" },
                { value: "remove", label: "Removing access" }]}
              onChange={(v) => setTweak("fail_mode", v)} />
            <TweakRadio label="Row style" value={t.row_style}
              options={[{ value: "borders", label: "Borders" }, { value: "zebra", label: "Zebra" }]}
              onChange={(v) => setTweak("row_style", v)} />
            <TweakRadio label="Card density" value={t.density}
              options={[{ value: "comfortable", label: "Comfortable" }, { value: "compact", label: "Compact" }]}
              onChange={(v) => setTweak("density", v)} />
          </TweakSection>
        </TweaksPanel>
      ) : null}
    </RolesProvider>
  );
}

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