/* global React, ReactDOM, ApiAuthProvider, AuthScreen, useAuth, useRoute, useToast, setAuthNextPath, validateBrowserReturnPath, TERMINAL_ONBOARDING_STEPS, Sidebar, Button, ToastProvider, Icon, LoadingSpinner, InsightsPage, RunsPage, RunDetailPage, WorkflowsPage, WorkflowEditorPage, WorkflowAnalyticsPage, SettingsPage, McpServersPage, CliTargetsPage, SourcesPage, InvitePage, ToolMonitorsPage, SignupPage, SigninPage, VerifyEmailPage, ResetPasswordPage, WorkspacePage, PlanPage, PlanReturnPage, RolePage, ConnectPage, MonitorPage, DonePage, PricingPage, OnboardingTour, LoopbackOAuthModalRoot, BenchmarkPage, OurMcpPage */

const { useEffect: useEffectApp, useRef: useRefApp, useState: useStateApp } = React;

// Onboarding steps that block tenant access. Mirrors the server-side
// BLOCKING_ONBOARDING_STEPS in lib/auth.js — any change here must be
// kept in sync there. Steps after 'plan' (role/connect/monitor/done)
// are skippable and don't block.
const BLOCKING_ONBOARDING_STEPS = new Set(['workspace', 'plan']);

// Subscription statuses that are NOT allowed to use the app shell. Skipped is
// handled separately so terminal skipped workspaces can browse read-only.
const BLOCKING_SUBSCRIPTION_STATUSES = new Set(['unpaid', 'past_due', 'canceled', 'refunded']);

function isKnownRoute(parts) {
  if (parts.length === 0) return true;
  if (parts[0] === 'signup' && parts.length === 1) return true;
  if (parts[0] === 'signup' && parts[1] === 'verify-email' && parts.length === 2) return true;
  if (parts[0] === 'signin' && parts.length === 1) return true;
  if (parts[0] === 'reset-password' && parts.length === 1) return true;
  if (parts[0] === 'pricing' && parts.length === 1) return true;
  if (parts[0] === 'auth' && parts[1] === 'callback' && parts.length === 2) return true;
  if (parts[0] === 'onboarding' && parts.length === 2) {
    return ['workspace', 'plan', 'role', 'connect', 'monitor', 'done'].includes(parts[1]);
  }
  if (parts[0] === 'onboarding' && parts[1] === 'plan' && parts[2] === 'return' && parts.length === 3) return true;
  if (parts[0] === 'dashboard' && parts.length === 1) return true;
  if (parts[0] === 'insights' && parts.length === 1) return true;
  if (parts[0] === 'insights' && parts[1] && parts.length === 2) return true;
  if (parts[0] === 'runs' && parts.length <= 2) return true;
  if (parts[0] === 'workflows' && parts[1] && parts[2] === 'analytics' && parts.length === 3) return true;
  if (parts[0] === 'workflows' && parts.length <= 2) return true;
  if (parts[0] === 'alerts' && parts.length === 1) return true;
  if (parts[0] === 'settings') {
    const section = parts[1] || 'organization';
    return parts.length <= 2 && ['organization', 'profile', 'api-keys', 'alerts', 'invitations', 'billing'].includes(section);
  }
  if (parts[0] === 'sources' && parts.length === 1) return true;
  if (parts[0] === 'sources' && parts[1] === 'mcp-servers' && parts.length === 2) return true;
  if (parts[0] === 'sources' && parts[1] === 'clis' && parts.length === 2) return true;
  if (['armature-mcp', 'our-mcp'].includes(parts[0]) && parts.length === 1) return true;
  if (parts[0] === 'tool-monitors' && parts.length === 1) return true;
  // Benchmark area is workflow-only: /benchmark and /benchmark/workflows
  // render the benchmark index, and /benchmark/workflows/:id is the
  // consolidated detail view. Batch detail is inlined under that view
  // (selected via ?batch=<id>). Source management lives under /sources/*.
  if (parts[0] === 'benchmark') {
    if (parts.length === 1) return true;
    if (parts[1] === 'workflows' && parts.length <= 3) return true;
    return false;
  }
  if (parts[0] === 'invite' && (parts.length === 2 || (parts.length === 3 && parts[2] === 'accept'))) return true;
  return false;
}

function isOnboardingRoute(parts) {
  return parts[0] === 'onboarding';
}

function currentOnboardingBlockPath(auth) {
  if (auth?.me?.role !== 'owner') return null;
  const step = auth?.me?.profile?.onboardingState?.currentStep;
  const status = auth?.me?.organization?.subscriptionStatus;
  if (status === 'skipped' && !TERMINAL_ONBOARDING_STEPS.has(step)) return '/onboarding/role';
  return BLOCKING_ONBOARDING_STEPS.has(step) ? `/onboarding/${step}` : null;
}

// Centralised "where does this org go home?" decision. The Insights
// page is the home — it's the landing route AND the post-onboarding
// / generic-fallback destination. /dashboard is a permanent redirect
// to /insights to preserve old bookmarks and in-app links.
const HOME_PATH = '/insights';

function renderOnboardingRoute(parts, queryString, navigate, home) {
  if (parts[0] === 'onboarding' && parts[1] === 'workspace') {
    return <WorkspacePage navigate={navigate} queryString={queryString} />;
  }
  if (parts[0] === 'onboarding' && parts[1] === 'plan' && parts[2] === 'return') {
    return <PlanReturnPage navigate={navigate} queryString={queryString} />;
  }
  if (parts[0] === 'onboarding' && parts[1] === 'plan') {
    return <PlanPage navigate={navigate} queryString={queryString} />;
  }
  if (parts[0] === 'onboarding' && parts[1] === 'role') {
    return <RolePage navigate={navigate} />;
  }
  // `/onboarding/connect|monitor|done` are no-op pages today; users
  // hit them either from old bookmarks or from the post-payment
  // redirect cycle. Bounce them straight to the org's home (Insights
  // when flag is ON, Dashboard when OFF).
  if (parts[0] === 'onboarding' && parts[1] === 'connect') {
    return <Redirect to={home} />;
  }
  if (parts[0] === 'onboarding' && parts[1] === 'monitor') {
    return <Redirect to={home} />;
  }
  if (parts[0] === 'onboarding' && parts[1] === 'done') {
    return <Redirect to={home} />;
  }
  return null;
}

function Redirect({ to }) {
  useEffectApp(() => {
    pushBrowserRoute(to);
  }, [to]);
  // Render the neutral app-shell skeleton during the one-frame gap between
  // pushBrowserRoute and the next render. Previously this returned
  // <AuthScreen />, which flashed the legacy sign-in/sign-up panel for ~1
  // frame on every internal redirect — including ones triggered after
  // successful auth (e.g. unconfigured → /onboarding/workspace).
  return <AppShellSkeleton />;
}

function isPublicRoute(parts) {
  return (parts[0] === 'signup' && parts.length === 1)
    || (parts[0] === 'signup' && parts[1] === 'verify-email' && parts.length === 2)
    || (parts[0] === 'signin' && parts.length === 1)
    || (parts[0] === 'reset-password' && parts.length === 1)
    || (parts[0] === 'pricing' && parts.length === 1)
    || (parts[0] === 'auth' && parts[1] === 'callback')
    || (parts[0] === 'invite' && parts.length === 2);
}

function NotFoundPage({ path, isAuthenticated, onPrimaryAction }) {
  return (
    <div className={`not-found-page ${isAuthenticated ? '' : 'not-found-public'}`}>
      <div className="not-found-shell">
        <div className="not-found-brand">
          <img src="/frontend/assets/armature-wordmark-dark.svg" alt="Armature" />
        </div>
        <div className="not-found-mark" aria-hidden="true">
          <span>404</span>
        </div>
        <div className="not-found-copy">
          <div className="not-found-kicker">Route not found</div>
          <h1>This page is outside the workspace map.</h1>
          <p>
            <span className="mono">{path || '/'}</span> is not a route in Armature.
          </p>
        </div>
        <div className="not-found-actions">
          <Button variant="primary" onClick={onPrimaryAction}>
            <Icon name={isAuthenticated ? 'activity' : 'key'} size={13} />
            {isAuthenticated ? 'Go to dashboard' : 'Sign in'}
          </Button>
        </div>
      </div>
    </div>
  );
}

const SUBSCRIPTION_HOLD_COPY = {
  unpaid: 'This workspace has no active subscription.',
  past_due: 'This workspace has a past-due payment.',
  canceled: 'This workspace subscription has been canceled.',
  refunded: 'This workspace subscription has been refunded.',
  skipped: 'This workspace needs to pick a plan.',
};

function SubscriptionHoldScreen({ status, onSignOut, mode = 'page', onClose = null }) {
  const headline = SUBSCRIPTION_HOLD_COPY[status] || 'This workspace billing needs attention.';
  const isModal = mode === 'modal';
  useEscapeToClose({
    enabled: isModal,
    onClose,
  });
  return (
    <div className={isModal ? 'subscription-hold-overlay' : 'not-found-page not-found-public'} role={isModal ? 'presentation' : undefined}>
      <div className={`not-found-shell ${isModal ? 'subscription-hold-modal' : ''}`} role={isModal ? 'dialog' : undefined} aria-modal={isModal ? 'true' : undefined}>
        <div className="not-found-brand">
          <img src="/frontend/assets/armature-wordmark-dark.svg" alt="Armature" />
        </div>
        <div className="not-found-copy">
          <div className="not-found-kicker">Workspace on hold</div>
          <h1>{headline}</h1>
          <p>The workspace owner needs to update billing before you can use Armature again.</p>
        </div>
        <div className="not-found-actions">
          {onClose && <Button variant="primary" onClick={onClose}>Close</Button>}
          {onSignOut && (
            <Button variant="ghost" onClick={onSignOut}>
              <Icon name="logOut" size={13} />Sign out
            </Button>
          )}
        </div>
      </div>
    </div>
  );
}

function AppShellSkeleton() {
  // Match the real Sidebar's three-group structure so loading → loaded has
  // no visual jump: same brand icon, same nav padding, same dividers.
  const SkelRow = () => (
    <div className="sidebar-link app-shell-skeleton-link">
      <div className="app-shell-skeleton-icon" aria-hidden="true"></div>
      <div className="app-shell-skeleton-line app-shell-skeleton-label"></div>
    </div>
  );
  return (
    <div className="app app-shell-skeleton">
      <aside className="sidebar app-shell-skeleton-sidebar" aria-hidden="true">
        <div className="sidebar-brand">
          <div className="sidebar-brand-logo">
            <img src="/frontend/assets/armature-app-icon.svg" alt="" />
          </div>
          <div className="sidebar-brand-copy">
            <div className="sidebar-brand-name">Armature</div>
            <div className="app-shell-skeleton-line app-shell-skeleton-org"></div>
          </div>
        </div>
        <nav className="sidebar-nav app-shell-skeleton-group"><SkelRow /></nav>
        <div className="sidebar-divider" aria-hidden="true"></div>
        <nav className="sidebar-nav app-shell-skeleton-group">
          <SkelRow /><SkelRow /><SkelRow />
        </nav>
        <div className="sidebar-divider" aria-hidden="true"></div>
        <nav className="sidebar-nav app-shell-skeleton-group"><SkelRow /></nav>
        <div className="sidebar-spacer"></div>
        <div className="sidebar-footer">
          <div className="avatar"></div>
          <div className="sidebar-profile-copy">
            <div className="app-shell-skeleton-line"></div>
            <div className="app-shell-skeleton-line app-shell-skeleton-line-short"></div>
          </div>
        </div>
      </aside>
      <div className="main app-shell-skeleton-main">
        <div className="app-shell-skeleton-topbar">
          <div className="app-shell-skeleton-line app-shell-skeleton-title"></div>
        </div>
        <div className="app-shell-skeleton-content">
          <div className="code inline-loading app-shell-skeleton-loader">
            <LoadingSpinner size="sm" label="Loading workspace" decorative />
            Loading workspace...
          </div>
        </div>
      </div>
    </div>
  );
}

function buildMcpOAuthReturnPath(searchParams) {
  const returnParams = new URLSearchParams();
  const serverId = searchParams.get('server');
  const profileId = searchParams.get('profile');
  const reason = searchParams.get('reason');
  if (!serverId) return '/sources/mcp-servers';
  returnParams.set('server', serverId);
  if (profileId) returnParams.set('profile', profileId);
  if (reason) returnParams.set('reason', reason);
  const suffix = returnParams.toString();
  return `/sources/mcp-servers${suffix ? `?${suffix}` : ''}`;
}

function isEditableShortcutTarget(target) {
  if (!target || typeof target !== 'object') return false;
  for (let node = target; node && typeof node === 'object'; node = node.parentElement || node.parentNode) {
    const tagName = String(node.tagName || '').toLowerCase();
    if (['input', 'textarea', 'select'].includes(tagName)) return true;
    if (typeof node.getAttribute === 'function') {
      const contentEditable = node.getAttribute('contenteditable');
      if (contentEditable === 'false') return false;
      if (contentEditable === '' || contentEditable === 'true') return true;
    }
    if (node.isContentEditable) return true;
  }
  return false;
}

function AppBody() {
  const { parts, queryString, navigate } = useRoute();
  const auth = useAuth();
  const toast = useToast();
  const [sidebarCollapsed, setSidebarCollapsed] = useStateApp(() => window.innerWidth <= 1280);
  const [paymentHold, setPaymentHold] = useStateApp(null);
  const signOutInFlightRef = useRefApp(false);
  const routeIsKnown = isKnownRoute(parts);
  const routePath = `/${parts.join('/')}${queryString ? `?${queryString}` : ''}`;

  useEffectApp(() => {
    const media = window.matchMedia('(max-width: 1280px)');
    function collapseWhenNarrow(event) {
      if (event.matches) setSidebarCollapsed(true);
    }
    collapseWhenNarrow(media);
    media.addEventListener?.('change', collapseWhenNarrow);
    return () => media.removeEventListener?.('change', collapseWhenNarrow);
  }, []);

  useEffectApp(() => {
    function onSidebarShortcut(event) {
      if (!(event.metaKey || event.ctrlKey) || event.altKey || event.shiftKey || event.repeat || String(event.key).toLowerCase() !== 'b') return;
      if (isEditableShortcutTarget(event.target)) return;
      event.preventDefault();
      setSidebarCollapsed(c => !c);
    }
    document.addEventListener('keydown', onSidebarShortcut);
    return () => document.removeEventListener('keydown', onSidebarShortcut);
  }, []);

  useEffectApp(() => {
    const searchParams = new URLSearchParams(window.location.search);
    const oauthStatus = searchParams.get('oauth');
    const oauthReturnPath = buildMcpOAuthReturnPath(searchParams);
    if (oauthStatus === 'connected') {
      navigate(oauthReturnPath, { replace: true });
      return;
    }
    if (oauthStatus === 'error') {
      toast.show({
        tone: 'bad',
        title: 'OAuth failed',
        description: searchParams.get('message') || 'OAuth authorization did not complete.',
      });
      navigate(oauthReturnPath, { replace: true });
      return;
    }
    if (oauthStatus === 'pending') {
      toast.show({
        tone: 'warn',
        title: 'OAuth completed; provisioning is still in progress',
        description: 'Tools will appear once provisioning finishes.',
      });
      navigate(oauthReturnPath, { replace: true });
    }
  }, [navigate, toast]);

  useEffectApp(() => {
    function onPaymentRequired(event) {
      const currentReturnTo = validateBrowserReturnPath(routePath) || HOME_PATH;
      const returnTo = validateBrowserReturnPath(event.detail?.returnTo) || currentReturnTo;
      if (auth.me?.role === 'owner') {
        navigate(`/settings/billing?source=paywall&return_to=${encodeURIComponent(returnTo)}`);
        return;
      }
      setPaymentHold({ ...event.detail, returnTo });
    }
    window.addEventListener('armature:payment-required', onPaymentRequired);
    return () => window.removeEventListener('armature:payment-required', onPaymentRequired);
  }, [auth.me?.role, routePath, navigate]);

  useEffectApp(() => {
    function onTenantActionDenied(event) {
      toast.show({
        tone: 'warn',
        title: 'Action unavailable',
        description: event.detail?.message || 'Your role cannot perform this action.',
      });
    }
    window.addEventListener('armature:tenant-action-denied', onTenantActionDenied);
    return () => window.removeEventListener('armature:tenant-action-denied', onTenantActionDenied);
  }, [toast]);

  if (auth.status === 'bootstrapping') {
    return auth.hasStoredSession ? <AppShellSkeleton /> : <AuthScreen />;
  }

  if (parts[0] === 'signup' && parts[1] === 'verify-email') {
    return <VerifyEmailPage navigate={navigate} queryString={queryString} />;
  }

  if (parts[0] === 'signup') {
    return <SignupPage navigate={navigate} queryString={queryString} />;
  }

  if (parts[0] === 'signin') {
    return <SigninPage navigate={navigate} queryString={queryString} />;
  }

  if (parts[0] === 'reset-password') {
    return <ResetPasswordPage navigate={navigate} queryString={queryString} />;
  }

  if (parts[0] === 'pricing' && !auth.me) {
    return <PricingPage navigate={navigate} queryString={queryString} />;
  }

  if (parts[0] === 'invite' && parts[1] && parts.length === 2) {
    return <InvitePage token={parts[1]} navigate={navigate} />;
  }

  if (!routeIsKnown && !auth.me && !auth.error) {
    return (
      <NotFoundPage
        path={`/${parts.join('/')}`}
        isAuthenticated={false}
        onPrimaryAction={() => navigate('/')} />
    );
  }

  const hasSessionWithoutMembership = auth.status === 'unconfigured';
  if (!auth.me) {
    if (hasSessionWithoutMembership) {
      // Hold on the auth-callback URLs while completeAuthCallback finishes
      // rewriting the URL to the post-auth target. Supabase's
      // onAuthStateChange fires inside exchangeCodeForSession and queues a
      // refreshMe(); if that refreshMe resolves before finishAuthCallbackUrl
      // runs, status flips to 'unconfigured' while parts is still ['auth',
      // 'callback']. Falling through to the workspace redirect here would
      // strand invitees (whose ?next= points at /invite/<token>/accept).
      //
      // Excludes auth.status === 'error': if completeAuthCallback threw
      // (OAuth denied, expired PKCE/OTP, etc.), the URL never gets rewritten
      // and onAuthStateChange won't fire again. Holding on the skeleton
      // would strand the user. Fall through to the next branches so they
      // can recover.
      if (parts[0] === 'auth' && parts[1] === 'callback' && auth.status !== 'error') {
        return <AppShellSkeleton />;
      }
      if (parts[0] === 'workspace' && parts[1] === 'workspace' && auth.status !== 'error') {
        return <AppShellSkeleton />;
      }
      if (parts[0] === 'onboarding' && parts[1] === 'workspace') {
        return <WorkspacePage navigate={navigate} queryString={queryString} />;
      }
      if (parts[0] === 'onboarding' && parts[1] === 'plan' && queryString) {
        return <Redirect to={`/onboarding/workspace?${queryString}`} />;
      }
      if (parts[0] === 'invite' && parts[2] === 'accept') {
        return <InvitePage token={parts[1]} navigate={navigate} acceptRedirect="/onboarding/role" autoRedirectOnAccept />;
      }
      return <Redirect to="/onboarding/workspace" />;
    }
    // Unauthenticated user on /invite/<token>/accept: don't bounce to /signup
    // (which would flash the SignupPage and lose the invite context). Redirect
    // back to the public invite-preview page so they can retry Google or
    // email/password without leaving the invite flow.
    if (parts[0] === 'invite' && parts[1] && parts[2] === 'accept') {
      return <Redirect to={`/invite/${parts[1]}`} />;
    }
    if (!isPublicRoute(parts)) {
      setAuthNextPath(`/${parts.join('/')}${queryString ? `?${queryString}` : ''}`);
      const unauthenticatedRedirect = auth.status === 'unauthenticated' && auth.error
        ? '/signin'
        : '/signup';
      return <Redirect to={unauthenticatedRedirect} />;
    }
    // On the auth-callback URLs, hold on the skeleton instead of flashing
    // the legacy AuthScreen between completeAuthCallback's PKCE exchange and
    // its URL rewrite. /auth/callback and /workspace/workspace are public
    // routes so they fall through here; without this guard the user briefly
    // sees the sign-in/sign-up panel after a successful authentication.
    //
    // Excludes auth.status === 'error': if completeAuthCallback threw
    // (OAuth denied, expired PKCE code, expired OTP, etc.), the URL never
    // gets rewritten and onAuthStateChange won't fire again. Falling
    // through to AuthScreen lets the user see the error and recover —
    // holding on the skeleton would strand them on a permanent loading
    // screen.
    if (parts[0] === 'auth' && parts[1] === 'callback' && auth.status !== 'error') {
      return <AppShellSkeleton />;
    }
    if (parts[0] === 'workspace' && parts[1] === 'workspace' && auth.status !== 'error') {
      return <AppShellSkeleton />;
    }
    return <AuthScreen />;
  }

  let pageEl;
  let activeKey = parts[0] || 'dashboard';
  const isOwner = auth.me.role === 'owner';
  const subscriptionStatus = auth.me.organization?.subscriptionStatus;
  const isPlanAllowedRoute = (parts[0] === 'onboarding' && parts[1] === 'plan')
    || (parts[0] === 'settings' && parts[1] === 'billing')
    || parts[0] === 'pricing';
  const subscriptionBlocks = BLOCKING_SUBSCRIPTION_STATUSES.has(subscriptionStatus);
  const currentStepValue = auth.me?.profile?.onboardingState?.currentStep;
  const onboardingComplete = TERMINAL_ONBOARDING_STEPS.has(currentStepValue);
  const currentPath = `/${parts.join('/')}`;
  const isSubscriptionRecoveryRoute = isOwner && subscriptionBlocks && isPlanAllowedRoute;

  if (subscriptionStatus === 'unpaid' && isOwner && !isPlanAllowedRoute) {
    const planQuerySuffix = parts[0] === 'onboarding' && parts[1] === 'workspace' && queryString ? `?${queryString}` : '';
    return <Redirect to={`/onboarding/plan${planQuerySuffix}`} />;
  }
  if (subscriptionStatus === 'skipped' && !onboardingComplete && currentPath !== '/onboarding/role') {
    return <Redirect to="/onboarding/role" />;
  }
  if (isOwner && subscriptionBlocks && !isPlanAllowedRoute) {
    return <Redirect to="/settings/billing" />;
  }
  // Non-owner members can't fix the org's billing — show them a hold screen
  // instead of letting them into the app or bouncing them to /onboarding/plan
  // (which they can't act on).
  if (!isOwner && subscriptionBlocks) {
    return <SubscriptionHoldScreen status={subscriptionStatus} onSignOut={signOutToSignin} />;
  }

  const blockedOnboardingPath = currentOnboardingBlockPath(auth);
  const isBlockedOnboardingAllowedRoute = blockedOnboardingPath === '/onboarding/plan'
    && currentPath === '/onboarding/plan/return';
  if (blockedOnboardingPath && currentPath !== blockedOnboardingPath && !isBlockedOnboardingAllowedRoute) {
    return <Redirect to={blockedOnboardingPath} />;
  }

  if (!isOwner && isOnboardingRoute(parts) && !onboardingComplete && currentPath !== '/onboarding/role') {
    return <Redirect to="/onboarding/role" />;
  }

  if (isOnboardingRoute(parts) && onboardingComplete && !isSubscriptionRecoveryRoute) {
    return <Redirect to={HOME_PATH} />;
  }

  if (isOnboardingRoute(parts)) {
    const onboardingEl = renderOnboardingRoute(parts, queryString, navigate, HOME_PATH);
    if (onboardingEl) return onboardingEl;
  }

  // A user mid-onboarding (currentStep is not 'done' or 'dashboard') hitting
  // an unknown route should NOT see the in-app shell — that exposed the
  // sidebar (Dashboard/Runs/Workflows nav) before they finished setup. Show
  // the public 404 and bounce them back to their current step (or /role as
  // a sensible fallback for unrecognized step values).
  if (!routeIsKnown && !onboardingComplete) {
    const resumePath = ['role', 'connect', 'monitor'].includes(currentStepValue)
      ? `/onboarding/${currentStepValue}`
      : '/onboarding/role';
    return (
      <NotFoundPage
        path={`/${parts.join('/')}`}
        isAuthenticated={false}
        onPrimaryAction={() => navigate(resumePath)} />
    );
  }

  if (!routeIsKnown) {
    pageEl = (
      <NotFoundPage
        path={`/${parts.join('/')}`}
        isAuthenticated
        onPrimaryAction={() => navigate(HOME_PATH)} />
    );
    activeKey = '';
  } else if (parts[0] === 'runs') {
    if (parts[1]) {
      pageEl = <RunDetailPage runId={parts[1]} navigate={navigate} />;
    } else {
      pageEl = <RunsPage navigate={navigate} queryString={queryString} />;
    }
  } else if (parts[0] === 'workflows') {
    if (parts[1] && parts[2] === 'analytics') {
      pageEl = <WorkflowAnalyticsPage workflowId={parts[1]} navigate={navigate} queryString={queryString} />;
    } else if (parts[1]) {
      pageEl = <WorkflowEditorPage workflowId={parts[1]} navigate={navigate} />;
    } else {
      pageEl = <WorkflowsPage navigate={navigate} queryString={queryString} />;
    }
  } else if (parts[0] === 'alerts') {
    // /alerts moved into Settings → Alerts. Preserve any query string (notably
    // ?slackInstall=success|failed from the OAuth fallback redirect) so the
    // settings panel can react to the install signal exactly the same way the
    // legacy /alerts page did.
    const settingsAlertsPath = queryString ? `/settings/alerts?${queryString}` : '/settings/alerts';
    return <Redirect to={settingsAlertsPath} />;
  } else if (parts[0] === 'settings') {
    pageEl = <SettingsPage section={parts[1] || 'organization'} navigate={navigate} queryString={queryString} />;
    activeKey = '';
  } else if (parts[0] === 'our-mcp') {
    return <Redirect to={queryString ? `/armature-mcp?${queryString}` : '/armature-mcp'} />;
  } else if (parts[0] === 'armature-mcp') {
    pageEl = <OurMcpPage navigate={navigate} queryString={queryString} />;
    activeKey = 'our-mcp';
  } else if (parts[0] === 'pricing') {
    pageEl = <PricingPage navigate={navigate} queryString={queryString} />;
    activeKey = '';
  } else if (parts[0] === 'invite' && parts[1] && parts[2] === 'accept') {
    pageEl = <InvitePage token={parts[1]} navigate={navigate} acceptRedirect="/onboarding/role" autoRedirectOnAccept />;
    activeKey = '';
  } else if (parts[0] === 'sources') {
    // Single sidebar entry "My MCPs & CLIs" lands on /sources (combined page).
    // /sources/mcp-servers and /sources/clis remain valid deep-link routes
    // and render the single-kind page as before; the sidebar entry stays
    // highlighted in all three cases.
    if (parts[1] === 'mcp-servers') {
      pageEl = <McpServersPage navigate={navigate} queryString={queryString} />;
    } else if (parts[1] === 'clis') {
      pageEl = <CliTargetsPage navigate={navigate} />;
    } else {
      pageEl = <SourcesPage navigate={navigate} queryString={queryString} />;
    }
    activeKey = 'sources';
  } else if (parts[0] === 'tool-monitors') {
    pageEl = <ToolMonitorsPage navigate={navigate} queryString={queryString} />;
    activeKey = 'tool-monitors';
  } else if (parts[0] === 'insights') {
    pageEl = <InsightsPage navigate={navigate} reportId={parts[1] || null} queryString={queryString} />;
    activeKey = 'insights';
  } else if (parts[0] === 'dashboard') {
    // /dashboard is a permanent redirect to /insights so old bookmarks,
    // in-app links, and the app icon funnel into one canonical home.
    // We preserve the query string so any bookmarked time-range or
    // filter survives the redirect.
    return <Redirect to={queryString ? `/insights?${queryString}` : '/insights'} />;
  } else if (parts[0] === 'benchmark') {
    // BenchmarkPage's only legitimate sections are undefined and
    // 'workflows' — recordId carries the workflow id when present. The
    // legacy /benchmark/batches/:id route was removed; deep links to a
    // specific batch now live as ?batch=<id> on the workflow detail.
    pageEl = (
      <BenchmarkPage
        navigate={navigate}
        queryString={queryString}
        section={parts[1] || 'workflows'}
        recordId={parts[2] || null}
      />
    );
    activeKey = 'benchmark';
  } else {
    pageEl = <InsightsPage navigate={navigate} reportId={null} queryString={queryString} />;
    activeKey = 'insights';
  }

  async function signOutToSignin() {
    if (signOutInFlightRef.current) return;
    signOutInFlightRef.current = true;
    try {
      await auth.signOut();
    } catch (error) {
      console.error('Sign out failed', error);
    } finally {
      signOutInFlightRef.current = false;
      navigate('/signin');
    }
  }

  return (
    <div className={`app ${sidebarCollapsed ? 'sidebar-collapsed' : ''}`}>
      <Sidebar
        activeKey={activeKey}
        onNav={navigate}
        me={auth.me}
        collapsed={sidebarCollapsed}
        onToggleCollapse={() => setSidebarCollapsed(c => !c)}
        onSignOut={signOutToSignin} />
      <div className="main">
        <div className="page">
          {pageEl}
        </div>
      </div>
      {paymentHold && (
        <SubscriptionHoldScreen
          status={paymentHold.subscriptionStatus}
          mode="modal"
          onClose={() => setPaymentHold(null)}
          onSignOut={signOutToSignin} />
      )}
      <OnboardingTour navigate={navigate} />
    </div>
  );
}

function App() {
  return (
    <ApiAuthProvider>
      <ToastProvider>
        <AppBody />
        {/* Singleton controller for the OAuth loopback paste-back flow.
            Mounted once at the root so any descendant (the production
            Connect MCP modal, the onboarding connect form, future
            features) can call `presentLoopbackOAuthFlow` without each
            having to render its own copy. The component is idempotent;
            multiple mounts are safe but only the latest one handles
            in-flight flows, so a single root mount is the cleanest spot. */}
        <LoopbackOAuthModalRoot />
      </ToastProvider>
    </ApiAuthProvider>
  );
}

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