import { Navigate, Outlet, useLocation } from 'react-router-dom';
// Use the Datadog-wrapped createBrowserRouter so RUM sees route templates
// (e.g. /cmdb/devices/:id) instead of per-ID URLs. Pairs with reactPlugin({ router: true })
// in src/lib/rum.ts. The dashboard runs react-router-dom v7, so we pull from the v7 entry.
import { createBrowserRouter } from '@datadog/browser-rum-react/react-router-v7';
import { ErrorBoundary as DatadogErrorBoundary } from '@datadog/browser-rum-react';
import { useQuery } from '@tanstack/react-query';
import { AppShell } from './layout/AppShell';
import { useAuthStore } from '@/stores/auth-store';
import { useFeatureStore } from '@/stores/feature-store';
import { PermissionGuard } from '@/components/PermissionGuard';
import { ErrorDetailsBlock } from '@/components/ErrorDetailsBlock';
import { P } from '@/lib/permissions';
import { type ReactNode, lazy, Suspense, useEffect } from 'react';
import { getMe } from '@/lib/auth';
import { createLogger } from '@/lib/logger';
import { captureKioskTokenFromUrl, getKioskToken } from '@/features/monitoring/kiosk-token';
import { useRumIdentity } from '@/hooks/useRumIdentity';

const log = createLogger('Router');

/**
 * Wraps a dynamic import with retry + auto-refresh for stale chunks.
 * After a deploy, old chunk hashes no longer exist on the server. This catches
 * the resulting import failure, retries once, and if it still fails, reloads the
 * page so the browser fetches the new HTML with updated chunk references.
 * A sessionStorage flag prevents infinite reload loops.
 */
function lazyWithRetry<T extends Record<string, any>>(
  importFn: () => Promise<T>,
  pick?: keyof T,
) {
  const resolve = (m: T) => {
    // Chunk loaded successfully — clear the reload guard so future deploys can trigger a fresh reload
    sessionStorage.removeItem('chunk_reload');
    return pick ? { default: m[pick] as React.ComponentType } : m;
  };

  return lazy(() =>
    importFn()
      .then(resolve)
      .catch(() => {
        // Retry once — the initial failure may be a transient network blip
        return importFn()
          .then(resolve)
          .catch(() => {
            const key = 'chunk_reload';
            if (!sessionStorage.getItem(key)) {
              sessionStorage.setItem(key, '1');
              window.location.reload();
            }
            // Return a no-op component to satisfy the type while the reload happens
            return { default: (() => null) as unknown as React.ComponentType };
          });
      }),
  );
}

// Pages
import { LoginPage } from './pages/LoginPage';
import { MfaVerifyPage } from './pages/MfaVerifyPage';
import { ForgotPasswordPage } from './pages/ForgotPasswordPage';
import { ResetPasswordPage } from './pages/ResetPasswordPage';
import { LandingPage } from './pages/LandingPage';
import { ErrorPage } from './pages/ErrorPage';

// Dashboard v2 is now the main dashboard mounted at `/`. The legacy
// DashboardPage and the experimental DashboardV3Page are kept around (files
// not deleted) but their imports + routes are commented so they don't ship.
// To re-enable either, uncomment the import line and the corresponding route.
// const DashboardPage = lazyWithRetry(() => import('./pages/DashboardPage'), 'DashboardPage');
const DashboardV2Page = lazyWithRetry(() => import('./pages/DashboardV2Page'), 'DashboardV2Page');
// const DashboardV3Page = lazyWithRetry(() => import('./pages/DashboardV3Page'), 'DashboardV3Page');
const SiteReachabilityPage = lazyWithRetry(() => import('./pages/SiteReachabilityPage'), 'SiteReachabilityPage');

// CMDB
const DevicesPage = lazyWithRetry(() => import('@/features/cmdb/pages/DevicesPage'), 'DevicesPage');
const TabletsPage = lazyWithRetry(() => import('@/features/cmdb/pages/TabletsPage'), 'TabletsPage');
const ServersPage = lazyWithRetry(() => import('@/features/cmdb/pages/ServersPage'), 'ServersPage');
const WorkstationsPage = lazyWithRetry(() => import('@/features/cmdb/pages/WorkstationsPage'), 'WorkstationsPage');
const DeviceDetailPage = lazyWithRetry(() => import('@/features/cmdb/pages/DeviceDetailPage'), 'DeviceDetailPage');
const ServerDetailPage = lazyWithRetry(() => import('@/features/cmdb/pages/ServerDetailPage'), 'ServerDetailPage');
const CreateDevicePage = lazyWithRetry(() => import('@/features/cmdb/pages/CreateDevicePage'), 'CreateDevicePage');
const IpamPage = lazyWithRetry(() => import('@/features/cmdb/pages/IpamPage'), 'IpamPage');
const SubnetMapPage = lazyWithRetry(() => import('@/features/cmdb/pages/SubnetMapPage'), 'SubnetMapPage');
const VlanListPage = lazyWithRetry(() => import('@/features/cmdb/pages/VlanListPage'), 'VlanListPage');
const SitesPage = lazyWithRetry(() => import('@/features/cmdb/pages/SitesPage'), 'SitesPage');
const DeviceReviewPage = lazyWithRetry(() => import('@/features/cmdb/pages/DeviceReviewPage'), 'DeviceReviewPage');
const SoftwareCanonicalReviewPage = lazyWithRetry(() => import('@/features/cmdb/pages/SoftwareCanonicalReviewPage'));
const PrintersPage = lazyWithRetry(() => import('@/features/cmdb/pages/PrintersPage'), 'PrintersPage');
const UpsPage = lazyWithRetry(() => import('@/features/cmdb/pages/UpsPage'), 'UpsPage');
const SoftwareInventoryPage = lazyWithRetry(() => import('@/features/cmdb/pages/SoftwareInventoryPage'), 'SoftwareInventoryPage');
const HardwareInventoryPage = lazyWithRetry(() => import('@/features/cmdb/pages/HardwareInventoryPage'), 'HardwareInventoryPage');
const DeviceTypeListPage = lazyWithRetry(() => import('@/features/cmdb/pages/DeviceTypeListPage'), 'DeviceTypeListPage');
const DeviceGroupListPage = lazyWithRetry(() => import('@/features/cmdb/pages/DeviceGroupListPage'), 'DeviceGroupListPage');

// Agent
const AgentListPage = lazyWithRetry(() => import('@/features/agent/pages/AgentListPage'));
const AgentDetailPage = lazyWithRetry(() => import('@/features/agent/pages/AgentDetailPage'));
const WorkstationDetailPage = lazyWithRetry(() => import('@/features/agent/pages/WorkstationDetailPage'));

// Remote Access
const RemoteSessionsPage = lazyWithRetry(() => import('@/features/remote-access/pages/RemoteSessionsPage'), 'RemoteSessionsPage');

// Monitoring
const MonitoringOverviewPage = lazyWithRetry(() => import('@/features/monitoring/pages/MonitoringOverviewPage'));
const MonitorDetailPage = lazyWithRetry(() => import('@/features/monitoring/pages/MonitorDetailPage'));
const ApplicationMonitorsPage = lazyWithRetry(() => import('@/features/monitoring/pages/ApplicationMonitorsPage'), 'ApplicationMonitorsPage');
const ApplicationMonitorDetailPage = lazyWithRetry(() => import('@/features/monitoring/pages/ApplicationMonitorDetailPage'), 'ApplicationMonitorDetailPage');
const MonitoringDisplayPage = lazyWithRetry(() => import('@/features/monitoring/pages/MonitoringDisplayPage'));
const SimpleModePage = lazyWithRetry(() => import('@/features/monitoring/pages/SimpleModePage'));
const MonitoringMapPage = lazyWithRetry(() => import('@/features/monitoring-map/pages/MonitoringMapPage'));
const BandwidthDashboardPage = lazyWithRetry(() => import('@/features/bandwidth/pages/BandwidthDashboardPage'));
const DeviceInterfacesPage = lazyWithRetry(() => import('@/features/bandwidth/pages/DeviceInterfacesPage'));

// Network
const NetworkDiscoveryPage = lazyWithRetry(() => import('@/features/network/pages/NetworkDiscoveryPage'));
const PendingReviewPage = lazyWithRetry(() => import('@/features/network/pages/PendingReviewPage'));
const TopologyMapPage = lazyWithRetry(() => import('@/features/network/pages/TopologyMapPage'));


// Tickets
const TicketListPage = lazyWithRetry(() => import('@/features/ticketing/pages/TicketListPage'), 'TicketListPage');
const TicketDetailPage = lazyWithRetry(() => import('@/features/ticketing/pages/TicketDetailPage'), 'TicketDetailPage');
const CreateTicketPage = lazyWithRetry(() => import('@/features/ticketing/pages/CreateTicketPage'), 'CreateTicketPage');

// SIEM
const SiemDashboardPage = lazyWithRetry(() => import('@/features/siem/pages/SiemDashboardPage'), 'SiemDashboardPage');
const AuditTrailPage = lazyWithRetry(() => import('@/features/siem/pages/AuditTrailPage'), 'AuditTrailPage');
const AuditEntryDetailPage = lazyWithRetry(() => import('@/features/siem/pages/AuditEntryDetailPage'), 'AuditEntryDetailPage');
const LogExplorerPage = lazyWithRetry(() => import('@/features/siem/pages/LogExplorerPage'), 'LogExplorerPage');
const EmailSecurityPage = lazyWithRetry(() => import('@/features/siem/pages/EmailSecurityPage'), 'EmailSecurityPage');
const EventClassifiersPage = lazyWithRetry(() => import('@/features/siem/pages/EventClassifiersPage'), 'EventClassifiersPage');
const SyslogSourcesPage = lazyWithRetry(() => import('@/features/siem/pages/SyslogSourcesPage'), 'SyslogSourcesPage');
const NetworkFlowLogsPage = lazyWithRetry(() => import('@/features/siem/pages/NetworkFlowLogsPage'), 'NetworkFlowLogsPage');
const TracesPage = lazyWithRetry(() => import('@/features/siem/pages/TracesPage'), 'TracesPage');

// Settings
const GeneralSettingsPage = lazyWithRetry(() => import('@/features/settings/pages/GeneralSettingsPage'), 'GeneralSettingsPage');
const BrandingSettingsPage = lazyWithRetry(() => import('@/features/settings/pages/BrandingSettingsPage'), 'BrandingSettingsPage');
const UserManagementPage = lazyWithRetry(() => import('@/features/settings/pages/UserManagementPage'), 'UserManagementPage');
const TenantManagementPage = lazyWithRetry(() => import('@/features/settings/pages/TenantManagementPage'), 'TenantManagementPage');
const TenantSsoPage = lazyWithRetry(() => import('@/features/sso/pages/TenantSsoPage'), 'TenantSsoPage');
const MspSsoPage = lazyWithRetry(() => import('@/features/sso/pages/MspSsoPage'), 'MspSsoPage');
const ApiKeysPage = lazyWithRetry(() => import('@/features/settings/pages/ApiKeysPage'), 'ApiKeysPage');
const DeviceTypesPage = lazyWithRetry(() => import('@/features/settings/pages/DeviceTypesPage'), 'DeviceTypesPage');
const DepartmentManagementPage = lazyWithRetry(() => import('@/features/settings/pages/DepartmentManagementPage'), 'DepartmentManagementPage');
const SiteLocationsPage = lazyWithRetry(() => import('@/features/settings/pages/SiteLocationsPage'), 'SiteLocationsPage');
const DeviceGroupManagementPage = lazyWithRetry(() => import('@/features/settings/pages/DeviceGroupManagementPage'), 'DeviceGroupManagementPage');
const TagManagementPage = lazyWithRetry(() => import('@/features/settings/pages/TagManagementPage'), 'TagManagementPage');
const CmdbConfigPage = lazyWithRetry(() => import('@/features/settings/pages/CmdbConfigPage'), 'CmdbConfigPage');
const EmailTemplatePage = lazyWithRetry(() => import('@/features/settings/pages/EmailTemplatePage'), 'EmailTemplatePage');
const DeviceCredentialsPage = lazyWithRetry(() => import('@/features/settings/pages/DeviceCredentialsPage'), 'DeviceCredentialsPage');
const CredentialsListPage = lazyWithRetry(() => import('@/features/credentials/pages/CredentialsListPage'));
const CredentialDetailPage = lazyWithRetry(() => import('@/features/credentials/pages/CredentialDetailPage'));
const SnmpMibProfilesPage = lazyWithRetry(() => import('@/features/settings/pages/SnmpMibProfilesPage'), 'SnmpMibProfilesPage');
const MibProfileReposPage = lazyWithRetry(() => import('@/features/settings/pages/MibProfileReposPage'), 'MibProfileReposPage');
const AlertRulesPage = lazyWithRetry(() => import('@/features/settings/pages/AlertRulesPage'), 'AlertRulesPage');
const AgentConfigPage = lazyWithRetry(() => import('@/features/settings/pages/AgentConfigPage'), 'AgentConfigPage');
const UserGroupManagementPage = lazyWithRetry(() => import('@/features/settings/pages/UserGroupManagementPage'), 'UserGroupManagementPage');
const UserGroupEditorPage = lazyWithRetry(() => import('@/features/settings/pages/UserGroupEditorPage'), 'UserGroupEditorPage');
const SecuritySettingsPage = lazyWithRetry(() => import('@/features/settings/pages/SecuritySettingsPage'), 'SecuritySettingsPage');
const NotificationSettingsPage = lazyWithRetry(() => import('@/features/settings/pages/NotificationSettingsPage'), 'NotificationSettingsPage');

// Universal Groups — unified hierarchical group tree replacing user-groups + departments
// (feature-flag `groups`; legacy pages redirect to this workspace when the flag is on,
// see GroupsFlagRedirect below).
const GroupsWorkspacePage = lazyWithRetry(() => import('@/features/groups/pages/GroupsWorkspacePage'), 'GroupsWorkspacePage');

// Import
const ImportPage = lazyWithRetry(() => import('@/features/import/pages/ImportPage'), 'ImportPage');

// Profile
const ProfilePage = lazyWithRetry(() => import('@/features/profile/pages/ProfilePage'), 'ProfilePage');

// Automation — Scripts library (ITPA, Phase 0b+1+2 MVP)
const ScriptsLibraryPage = lazyWithRetry(() => import('@/features/automation/pages/ScriptsLibraryPage'), 'ScriptsLibraryPage');
const ScriptDetailPage = lazyWithRetry(() => import('@/features/automation/pages/ScriptDetailPage'), 'ScriptDetailPage');
const ScriptEditorPage = lazyWithRetry(() => import('@/features/automation/pages/ScriptEditorPage'), 'ScriptEditorPage');

// ITKM — Knowledge Base / file repository (Phase A1) + articles + share viewer (Phase A2)
// lazyWithRetry's `pick` arg already picks the named export — don't .then-wrap
// to a default, that double-resolves and lazy() ends up with undefined.
const FilesPage = lazyWithRetry(() => import('@/features/files/pages/FilesPage'), 'FilesPage');
const KbArticleListPage = lazyWithRetry(() => import('@/features/kb/pages/ArticleListPage'), 'ArticleListPage');
const KbArticleDetailPage = lazyWithRetry(() => import('@/features/kb/pages/ArticleDetailPage'), 'ArticleDetailPage');
const KbArticleEditorPage = lazyWithRetry(() => import('@/features/kb/pages/ArticleEditorPage'), 'ArticleEditorPage');
const KbSharedArticlePage = lazyWithRetry(() => import('@/features/kb/pages/SharedArticlePage'), 'SharedArticlePage');

// PSA / Billing
const ClientListPage = lazyWithRetry(() => import('@/features/psa/pages/ClientListPage'), 'ClientListPage');
const ClientDetailPage = lazyWithRetry(() => import('@/features/psa/pages/ClientDetailPage'), 'ClientDetailPage');
const ProductCatalogPage = lazyWithRetry(() => import('@/features/psa/pages/ProductCatalogPage'), 'ProductCatalogPage');
const ContractListPage = lazyWithRetry(() => import('@/features/psa/pages/ContractListPage'), 'ContractListPage');
const ContractDetailPage = lazyWithRetry(() => import('@/features/psa/pages/ContractDetailPage'), 'ContractDetailPage');
const SowDetailPage = lazyWithRetry(() => import('@/features/psa/pages/SowDetailPage'), 'SowDetailPage');
const InvoiceListPage = lazyWithRetry(() => import('@/features/psa/pages/InvoiceListPage'), 'InvoiceListPage');
const TimeEntryListPage = lazyWithRetry(() => import('@/features/psa/pages/TimeEntryListPage'), 'TimeEntryListPage');
// Expenses — mileage, vehicles, trip expenses — FEATURE_EXPENSES_MILEAGE
const MileageListPage = lazyWithRetry(() => import('@/features/expenses/pages/MileageListPage'), 'MileageListPage');
const VehicleListPage = lazyWithRetry(() => import('@/features/expenses/pages/VehicleListPage'), 'VehicleListPage');
const SoftwareLicenseListPage = lazyWithRetry(() => import('@/features/cmdb/pages/SoftwareLicenseListPage'), 'SoftwareLicenseListPage');
const MileageRatesPage = lazyWithRetry(() => import('@/features/expenses/pages/MileageRatesPage'), 'MileageRatesPage');
const MileageReportPage = lazyWithRetry(() => import('@/features/expenses/pages/MileageReportPage'), 'MileageReportPage');

// Unified Contacts — tenant-wide person records shared by PSA, CMDB and Sign
const ContactListPage = lazyWithRetry(() => import('@/features/contacts/pages/ContactListPage'), 'ContactListPage');
const ContactDetailPage = lazyWithRetry(() => import('@/features/contacts/pages/ContactDetailPage'), 'ContactDetailPage');

// E-Signature ("Sign")
const EsignEnvelopeListPage = lazyWithRetry(() => import('@/features/esign/pages/EsignEnvelopeListPage'), 'EsignEnvelopeListPage');
const EsignEnvelopeNewPage = lazyWithRetry(() => import('@/features/esign/pages/EsignEnvelopeNewPage'), 'EsignEnvelopeNewPage');
const EsignEnvelopeDetailPage = lazyWithRetry(() => import('@/features/esign/pages/EsignEnvelopeDetailPage'), 'EsignEnvelopeDetailPage');
const EsignSigningPortalPage = lazyWithRetry(() => import('@/features/esign/pages/EsignSigningPortalPage'), 'EsignSigningPortalPage');

// Billing Portal (customer-facing Stripe billing — MSP client tenants)
const PortalOverviewPage = lazyWithRetry(() => import('@/features/billing-portal/pages/PortalOverviewPage'), 'PortalOverviewPage');
const PortalInvoicesPage = lazyWithRetry(() => import('@/features/billing-portal/pages/PortalInvoicesPage'), 'PortalInvoicesPage');
const PortalPaymentMethodsPage = lazyWithRetry(() => import('@/features/billing-portal/pages/PortalPaymentMethodsPage'), 'PortalPaymentMethodsPage');
const PortalUsagePage = lazyWithRetry(() => import('@/features/billing-portal/pages/PortalUsagePage'), 'PortalUsagePage');

// Integrations
const IntegrationsPage = lazyWithRetry(() => import('@/features/integrations/pages/IntegrationsPage'), 'IntegrationsPage');

// RSS Feeds
const FeedsPage = lazyWithRetry(() => import('@/features/rss/pages/FeedsPage'), 'FeedsPage');

// Privacy & Compliance — cookie scanner
const WebPropertiesPage = lazyWithRetry(() => import('@/features/privacy/pages/WebPropertiesPage'), 'WebPropertiesPage');
const WebPropertyDetailPage = lazyWithRetry(() => import('@/features/privacy/pages/WebPropertyDetailPage'), 'WebPropertyDetailPage');
const CookieReviewPage = lazyWithRetry(() => import('@/features/privacy/pages/CookieReviewPage'), 'CookieReviewPage');

// Domain & Email Security Posture — SPF/DMARC/DKIM/MX monitoring
const PostureDomainsPage = lazyWithRetry(() => import('@/features/posture/pages/DomainsPage'), 'DomainsPage');
const PostureDomainDetailPage = lazyWithRetry(() => import('@/features/posture/pages/DomainDetailPage'), 'DomainDetailPage');

// Scheduled Tasks (tenant) + System Schedulers (admin)
const ScheduledTasksPage = lazyWithRetry(() => import('@/features/cron-tasks/pages/ScheduledTasksPage'));
const ScheduledTaskDetailPage = lazyWithRetry(() => import('@/features/cron-tasks/pages/ScheduledTaskDetailPage'));
const NewScheduledTaskPage = lazyWithRetry(() => import('@/features/cron-tasks/pages/NewScheduledTaskPage'));
const SystemSchedulersPage = lazyWithRetry(() => import('@/features/system-schedulers/pages/SystemSchedulersPage'));
const SystemSchedulerDetailPage = lazyWithRetry(() => import('@/features/system-schedulers/pages/SystemSchedulerDetailPage'));
const KmsAdminPage = lazyWithRetry(() => import('@/features/system/kms/pages/KmsAdminPage'));

// Reports
const ReportsPage = lazyWithRetry(() => import('@/features/reports/pages/ReportsPage'), 'ReportsPage');

// Changelog
const ChangelogPage = lazyWithRetry(() => import('@/features/changelog/pages/ChangelogPage'), 'ChangelogPage');

// Developer Tools
const DataOverviewPage = lazyWithRetry(() => import('@/features/devtools/pages/DataOverviewPage'), 'DataOverviewPage');
const RedisCacheExplorerPage = lazyWithRetry(() => import('@/features/devtools/pages/RedisCacheExplorerPage'), 'RedisCacheExplorerPage');
const HealthDashboardPage = lazyWithRetry(() => import('@/features/devtools/pages/HealthDashboardPage'), 'HealthDashboardPage');
const ApiDocumentationPage = lazyWithRetry(() => import('@/features/devtools/pages/ApiDocumentationPage'), 'ApiDocumentationPage');
const EnvironmentViewerPage = lazyWithRetry(() => import('@/features/devtools/pages/EnvironmentViewerPage'), 'EnvironmentViewerPage');
const RegistryViewerPage = lazyWithRetry(() => import('@/features/devtools/pages/RegistryViewerPage'), 'RegistryViewerPage');
const JobExplorerPage = lazyWithRetry(() => import('@/features/devtools/pages/JobExplorerPage'), 'JobExplorerPage');
const SatelliteAgentsPage = lazyWithRetry(() => import('@/features/devtools/pages/SatelliteAgentsPage'), 'SatelliteAgentsPage');
const CronPlaygroundPage = lazyWithRetry(() => import('@/features/devtools/pages/CronPlaygroundPage'), 'CronPlaygroundPage');
const StorageKvExplorerPage = lazyWithRetry(() => import('@/features/devtools/pages/StorageKvExplorerPage'), 'StorageKvExplorerPage');
const StorageKvPage = lazyWithRetry(() => import('@/features/automation/pages/StorageKvPage'), 'StorageKvPage');
const PermissionsPage = lazyWithRetry(() => import('@/features/permissions/pages/PermissionsPage'), 'PermissionsPage');
// Software Deployment pages use default-only exports — pass no pick arg so
// lazyWithRetry returns the module shape { default: Component } directly.
const SoftwareCatalogPage = lazyWithRetry(() => import('@/features/software-deployment/pages/CatalogPage'));
const SoftwarePackageDetailPage = lazyWithRetry(() => import('@/features/software-deployment/pages/PackageDetailPage'));
const SoftwareCohortsPage = lazyWithRetry(() => import('@/features/software-deployment/pages/CohortsPage'));
const SoftwareRolloutsPage = lazyWithRetry(() => import('@/features/software-deployment/pages/RolloutsPage'));
const SoftwareTenantRolloutDetailPage = lazyWithRetry(() => import('@/features/software-deployment/pages/TenantRolloutDetailPage'));
const SoftwareMspRolloutDetailPage = lazyWithRetry(() => import('@/features/software-deployment/pages/MspRolloutDetailPage'));
const SoftwareInstallHistoryPage = lazyWithRetry(() => import('@/features/software-deployment/pages/InstallHistoryPage'));

function ProtectedRoute({ children }: { children: ReactNode }) {
  const isAuthenticated = useAuthStore((s) => s.isAuthenticated);
  const isHydrating = useAuthStore((s) => s.isHydrating);
  const isBooting = useAuthStore((s) => s.isBooting);
  const user = useAuthStore((s) => s.user);
  const simpleModeFlag = useFeatureStore((s) => s.flags.simpleMode);
  const location = useLocation();
  useRumIdentity();

  // Hydrate the user profile via React Query.
  // Uses the same ['auth', 'me'] key as prefetchCriticalData — reads from cache if available.
  // The axios request interceptor handles token refresh proactively, so no manual ensureFreshToken needed.
  const meQuery = useQuery({
    queryKey: ['auth', 'me'],
    queryFn: getMe,
    enabled: isAuthenticated && !user && isHydrating,
    staleTime: 60_000,
    // Only retry network errors, not 4xx auth errors
    retry: (failureCount, error) => {
      const status = (error as any)?.response?.status ?? (error as any)?.status;
      if (status === 401 || status === 403) return false;
      return failureCount < 3;
    },
    retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 4000),
  });

  // Sync query result to auth store
  useEffect(() => {
    if (meQuery.data) {
      useAuthStore.getState().setUser(meQuery.data);
      useAuthStore.getState().setHydrating(false);
    }
  }, [meQuery.data]);

  // Handle auth errors — logout on 401/403
  useEffect(() => {
    if (!meQuery.error) return;
    const status = (meQuery.error as any)?.response?.status ?? (meQuery.error as any)?.status;
    if (status === 401 || status === 403) {
      log.warn('Hydration failed: auth error — logging out');
      useAuthStore.getState().logout();
    }
  }, [meQuery.error]);

  // Still resolving the boot-time silent refresh — don't decide auth state yet
  // (avoids bouncing a validly-logged-in user to /login before the refresh
  // cookie has been redeemed). Bootstrap awaits boot before render, so this is
  // a safety net for any re-entrant mount during boot.
  if (isBooting) {
    return (
      <div className="flex h-screen items-center justify-center text-muted-foreground">
        Loading...
      </div>
    );
  }

  if (!isAuthenticated) {
    // Show landing page at root; deep links go to /login with a redirect param
    // so re-authentication (e.g. after inactivity logout) returns to the same page.
    if (location.pathname === '/') {
      return <LandingPage />;
    }
    const redirectTarget = `${location.pathname}${location.search}${location.hash}`;
    log.warn(`Redirecting to login (unauthenticated): ${redirectTarget}`);
    return <Navigate to={`/login?redirect=${encodeURIComponent(redirectTarget)}`} replace />;
  }
  if (isHydrating) {
    return (
      <div className="flex h-screen items-center justify-center text-muted-foreground">
        {meQuery.isError ? (
          <div className="text-center space-y-2">
            <p>Unable to reach the server</p>
            <button
              onClick={() => meQuery.refetch()}
              className="text-sm text-primary hover:underline"
            >
              Try again
            </button>
          </div>
        ) : (
          'Loading...'
        )}
      </div>
    );
  }
  if (simpleModeFlag && user?.simpleMode && location.pathname !== '/dashboard/simple') {
    return <Navigate to="/dashboard/simple" replace />;
  }
  return <>{children}</>;
}

/**
 * Route wrapper for the monitoring display kiosk. Captures `?api_key=` on mount
 * into sessionStorage (and strips it from the URL), then allows access if either:
 *   - a kiosk token is present, OR
 *   - the user has a normal authenticated session (falls through to ProtectedRoute).
 * A missing kiosk token + unauthenticated user redirects to the landing page.
 */
function KioskOrProtectedRoute({ children }: { children: ReactNode }) {
  // Run URL capture synchronously on first render so subsequent logic sees the token.
  captureKioskTokenFromUrl();
  const kioskToken = getKioskToken();
  const isAuthenticated = useAuthStore((s) => s.isAuthenticated);

  if (kioskToken && !isAuthenticated) {
    // Kiosk-only mode — render the page directly without AppShell or the /me query.
    return <>{children}</>;
  }
  return <ProtectedRoute>{children}</ProtectedRoute>;
}

/**
 * Flag-gated redirect for the legacy user-groups / departments routes (D2b:
 * legacy pages stay mounted, but are superseded once Universal Groups ships).
 * When `flags.groups` is on, sends the user to the unified /settings/groups
 * workspace instead of the legacy element; otherwise renders `legacy` as-is.
 *
 * There's no static-route precedent for this in the tree below — `router` is
 * built once at module scope via `createBrowserRouter`, before feature flags
 * are hydrated from `/api/v1/config/features`, so a `{ element: <Navigate .../> }`
 * route entry can't react to the flag. This component re-reads the flag on
 * every render instead, exactly like the reactive `module` gating Sidebar.tsx
 * does for nav items. Intentionally sits OUTSIDE (wraps) the legacy element's
 * own <PermissionGuard> so a user who holds the NEW `settings.groups.view`
 * permission but not the legacy `settings.user-groups.*` / `settings.departments.*`
 * permission still gets redirected to the new page (which re-guards itself)
 * instead of being bounced to "/" by the legacy guard.
 */
function GroupsFlagRedirect({ legacy }: { legacy: ReactNode }) {
  const groupsEnabled = useFeatureStore((s) => s.flags.groups);
  if (groupsEnabled) {
    return <Navigate to="/settings/groups" replace />;
  }
  return <>{legacy}</>;
}

function SuspenseWrapper() {
  return (
    <Suspense fallback={<div className="flex items-center justify-center p-12 text-muted-foreground">Loading...</div>}>
      <Outlet />
    </Suspense>
  );
}

// Placeholder for pages that don't have a full implementation yet
function PlaceholderPage({ title }: { title: string }) {
  return (
    <div className="p-6">
      <h1 className="text-2xl font-bold">{title}</h1>
      <p className="text-muted-foreground mt-2">This page will be implemented with full features.</p>
    </div>
  );
}

// Fallback for the outer DatadogErrorBoundary. Datadog still receives the
// exception, while local users get a copyable payload for fast debugging.
function ShellErrorFallback({ error, resetError }: { error: Error; resetError: () => void }) {
  return (
    <div className="flex min-h-screen items-center justify-center p-6 text-center">
      <div className="w-full max-w-3xl space-y-4">
        <h1 className="text-2xl font-bold tracking-tight">Something went wrong</h1>
        <p className="text-sm text-muted-foreground">
          The dashboard hit an unexpected error. The issue was reported automatically. Try reloading the page.
        </p>
        <div className="flex items-center justify-center gap-3">
          <button
            className="rounded-md border px-4 py-2 text-sm hover:bg-muted"
            onClick={() => resetError()}
          >
            Try again
          </button>
          <button
            className="rounded-md bg-primary px-4 py-2 text-sm text-primary-foreground hover:opacity-90"
            onClick={() => window.location.reload()}
          >
            Reload
          </button>
        </div>
        <ErrorDetailsBlock error={error} context={{ boundary: 'DatadogErrorBoundary' }} />
      </div>
    </div>
  );
}

export const router = createBrowserRouter([
  {
    path: '/login',
    element: <LoginPage />,
  },
  {
    path: '/mfa/verify',
    element: <MfaVerifyPage />,
  },
  {
    path: '/forgot-password',
    element: <ForgotPasswordPage />,
  },
  {
    path: '/reset-password',
    element: <ResetPasswordPage />,
  },
  {
    // Public KB share-link viewer — no AppShell, anonymous (token + optional password)
    path: '/itkm/share/:token',
    element: (
      <Suspense fallback={<div className="flex items-center justify-center p-12 text-muted-foreground">Loading...</div>}>
        <KbSharedArticlePage />
      </Suspense>
    ),
  },
  {
    // Public e-signature signing portal — no AppShell, anonymous (tokenized link)
    path: '/esign/sign/:token',
    element: (
      <Suspense fallback={<div className="flex items-center justify-center p-12 text-muted-foreground">Loading...</div>}>
        <EsignSigningPortalPage />
      </Suspense>
    ),
  },
  {
    path: '/itim/monitoring/display',
    element: (
      <KioskOrProtectedRoute>
        <Suspense fallback={<div className="flex items-center justify-center p-12 text-muted-foreground">Loading...</div>}>
          <MonitoringDisplayPage />
        </Suspense>
      </KioskOrProtectedRoute>
    ),
  },
  {
    path: '/',
    element: (
      <DatadogErrorBoundary fallback={ShellErrorFallback}>
        <ProtectedRoute>
          <AppShell>
            <SuspenseWrapper />
          </AppShell>
        </ProtectedRoute>
      </DatadogErrorBoundary>
    ),
    errorElement: <ErrorPage />,
    children: [
      // v2 is now the main dashboard. Legacy DashboardPage at `/` and the
      // experimental DashboardV3Page are commented out; page files are kept.
      // { index: true, element: <DashboardPage /> },
      { index: true, element: <PermissionGuard permission={P.CMDB_DEVICES_VIEW}><DashboardV2Page /></PermissionGuard> },
      { path: 'dashboard/site-reachability', element: <PermissionGuard permission={P.CMDB_DEVICES_VIEW}><SiteReachabilityPage /></PermissionGuard> },
      // /dashboard-v2 stays mounted as a fallback URL so existing bookmarks
      // resolve to the same page that `/` now serves.
      { path: 'dashboard-v2', element: <PermissionGuard permission={P.CMDB_DEVICES_VIEW}><DashboardV2Page /></PermissionGuard> },
      { path: 'dashboard/simple', element: <SimpleModePage /> },
      // { path: 'dashboard-v3', element: <DashboardV3Page /> },

      // Profile
      { path: 'profile', element: <ProfilePage /> },

      // CMDB
      { path: 'cmdb/devices', element: <PermissionGuard permission={P.CMDB_DEVICES_VIEW}><DevicesPage /></PermissionGuard> },
      { path: 'cmdb/devices/new', element: <PermissionGuard permission={P.CMDB_DEVICES_CREATE}><CreateDevicePage /></PermissionGuard> },
      { path: 'cmdb/devices/:id', element: <PermissionGuard permission={P.CMDB_DEVICES_VIEW}><DeviceDetailPage /></PermissionGuard> },
      { path: 'cmdb/printers', element: <PermissionGuard permission={P.CMDB_DEVICES_VIEW}><PrintersPage /></PermissionGuard> },
      { path: 'cmdb/ups', element: <PermissionGuard permission={P.CMDB_DEVICES_VIEW}><UpsPage /></PermissionGuard> },
      { path: 'cmdb/tablets', element: <PermissionGuard permission={P.CMDB_DEVICES_VIEW}><TabletsPage /></PermissionGuard> },
      { path: 'cmdb/tablets/:id', element: <PermissionGuard permission={P.CMDB_DEVICES_VIEW}><DeviceDetailPage /></PermissionGuard> },
      { path: 'cmdb/workstations', element: <PermissionGuard permission={P.CMDB_DEVICES_VIEW}><WorkstationsPage /></PermissionGuard> },
      { path: 'cmdb/workstations/:id', element: <PermissionGuard permission={P.CMDB_DEVICES_VIEW}><WorkstationDetailPage /></PermissionGuard> },
      { path: 'cmdb/servers', element: <PermissionGuard permission={P.CMDB_DEVICES_VIEW}><ServersPage /></PermissionGuard> },
      { path: 'cmdb/servers/:id', element: <PermissionGuard permission={P.CMDB_DEVICES_VIEW}><ServerDetailPage /></PermissionGuard> },
      // Generic catch-all for dynamic device type nav items
      { path: 'cmdb/type/:slug', element: <PermissionGuard permission={P.CMDB_DEVICES_VIEW}><DeviceTypeListPage /></PermissionGuard> },
      // Deep-link anchor: workspace with the device pre-selected (was DeviceDetailPage;
      // full detail lives at /cmdb/devices/:id). Tab anchors ride the #hash.
      { path: 'cmdb/type/:slug/:id', element: <PermissionGuard permission={P.CMDB_DEVICES_VIEW}><DeviceTypeListPage /></PermissionGuard> },
      // Aggregate view for nav-enabled device groups (rolls up every member type)
      { path: 'cmdb/group/:slug', element: <PermissionGuard permission={P.CMDB_DEVICES_VIEW}><DeviceGroupListPage /></PermissionGuard> },
      { path: 'cmdb/group/:slug/:id', element: <PermissionGuard permission={P.CMDB_DEVICES_VIEW}><DeviceDetailPage /></PermissionGuard> },
      // IPAM
      { path: 'ipam/subnets', element: <PermissionGuard permission={P.IPAM_ADDRESSES_VIEW}><IpamPage /></PermissionGuard> },
      { path: 'ipam/subnets/:id', element: <PermissionGuard permission={P.IPAM_ADDRESSES_VIEW}><SubnetMapPage /></PermissionGuard> },
      { path: 'ipam/vlans', element: <PermissionGuard permission={P.IPAM_ADDRESSES_VIEW}><VlanListPage /></PermissionGuard> },
      { path: 'cmdb/hardware', element: <PermissionGuard permission={P.CMDB_HARDWARE_STATS_VIEW}><HardwareInventoryPage /></PermissionGuard> },
      // Deep-link anchor: workspace with the component pre-selected (:id =
      // encodeURIComponent(`${componentType}:${name}`)) — v2 only; the v1
      // rollback page ignores the segment.
      { path: 'cmdb/hardware/:id', element: <PermissionGuard permission={P.CMDB_HARDWARE_STATS_VIEW}><HardwareInventoryPage /></PermissionGuard> },
      { path: 'cmdb/software', element: <PermissionGuard permission={P.CMDB_SOFTWARE_STATS_VIEW}><SoftwareInventoryPage /></PermissionGuard> },
      // Deep-link anchor: workspace with the program pre-selected (:id =
      // encodeURIComponent(name)) — v2 only; the v1 rollback page ignores it.
      { path: 'cmdb/software/:id', element: <PermissionGuard permission={P.CMDB_SOFTWARE_STATS_VIEW}><SoftwareInventoryPage /></PermissionGuard> },
      { path: 'cmdb/software-review', element: <PermissionGuard permission={P.CMDB_SOFTWARE_STATS_CURATE}><SoftwareCanonicalReviewPage /></PermissionGuard> },
      { path: 'cmdb/software-licenses', element: <PermissionGuard permission={P.CMDB_SOFTWARE_LICENSE_VIEW}><SoftwareLicenseListPage /></PermissionGuard> },
      { path: 'cmdb/sites', element: <PermissionGuard permission={[P.CMDB_SITES_VIEW, P.CMDB_SITES_MANAGE]}><SitesPage /></PermissionGuard> },
      { path: 'cmdb/review', element: <PermissionGuard permission={P.CMDB_DEVICES_EDIT}><DeviceReviewPage /></PermissionGuard> },

      // Agents
      { path: 'agents', element: <PermissionGuard permission={P.AGENT_AGENTS_VIEW}><AgentListPage /></PermissionGuard> },
      { path: 'agents/:id', element: <PermissionGuard permission={P.AGENT_AGENTS_VIEW}><AgentDetailPage /></PermissionGuard> },

      // Remote Access
      { path: 'remote-sessions', element: <PermissionGuard permission={P.AGENT_REMOTE_VIEW}><RemoteSessionsPage /></PermissionGuard> },

      // ITIM — Monitoring
      { path: 'itim/monitoring', element: <PermissionGuard permission={P.MONITORING_MONITORS_VIEW}><MonitoringOverviewPage /></PermissionGuard> },
      { path: 'itim/monitoring/map', element: <PermissionGuard permission={P.MONITORING_MONITORS_VIEW}><MonitoringMapPage /></PermissionGuard> },
      { path: 'itim/monitoring/bandwidth', element: <PermissionGuard permission={P.MONITORING_BANDWIDTH_VIEW}><BandwidthDashboardPage /></PermissionGuard> },
      { path: 'itim/monitoring/bandwidth/:deviceId', element: <PermissionGuard permission={P.MONITORING_BANDWIDTH_VIEW}><DeviceInterfacesPage /></PermissionGuard> },
      { path: 'itim/monitoring/app-monitors', element: <PermissionGuard permission={P.MONITORING_MONITORS_VIEW}><ApplicationMonitorsPage /></PermissionGuard> },
      { path: 'itim/monitoring/app-monitors/:id', element: <PermissionGuard permission={P.MONITORING_MONITORS_VIEW}><ApplicationMonitorDetailPage /></PermissionGuard> },
      { path: 'itim/monitoring/:id', element: <PermissionGuard permission={P.MONITORING_MONITORS_VIEW}><MonitorDetailPage /></PermissionGuard> },

      // ITIM — Alerting
      { path: 'itim/alerting/alert-rules', element: <PermissionGuard permission={[P.TICKETING_ALERT_RULES_VIEW, P.TICKETING_ALERT_RULES_MANAGE]}><AlertRulesPage /></PermissionGuard> },
      { path: 'itim/alerting/email-templates', element: <PermissionGuard permission={P.SETTINGS_EMAIL_TEMPLATES_VIEW}><EmailTemplatePage /></PermissionGuard> },

      // Network
      { path: 'network/discovery', element: <PermissionGuard permission={P.NETWORK_SCANS_VIEW}><NetworkDiscoveryPage /></PermissionGuard> },
      { path: 'network/scans', element: <PermissionGuard permission={P.NETWORK_SCANS_VIEW}><NetworkDiscoveryPage /></PermissionGuard> },
      { path: 'network/pending', element: <PermissionGuard permission={P.NETWORK_SCANS_VIEW}><PendingReviewPage /></PermissionGuard> },
      { path: 'network/topology', element: <PermissionGuard permission={P.NETWORK_SCANS_VIEW}><TopologyMapPage /></PermissionGuard> },

      // Tickets
      { path: 'tickets', element: <PermissionGuard permission={P.TICKETING_TICKETS_VIEW}><TicketListPage /></PermissionGuard> },
      { path: 'tickets/new', element: <PermissionGuard permission={P.TICKETING_TICKETS_CREATE}><CreateTicketPage /></PermissionGuard> },
      { path: 'tickets/:id', element: <PermissionGuard permission={P.TICKETING_TICKETS_VIEW}><TicketDetailPage /></PermissionGuard> },

      // SIEM
      { path: 'siem', element: <PermissionGuard permission={P.SIEM_DASHBOARD_VIEW}><SiemDashboardPage /></PermissionGuard> },
      { path: 'siem/audit', element: <PermissionGuard permission={P.SIEM_AUDIT_VIEW}><AuditTrailPage /></PermissionGuard> },
      { path: 'siem/audit/:id', element: <PermissionGuard permission={P.SIEM_AUDIT_VIEW}><AuditEntryDetailPage /></PermissionGuard> },
      { path: 'siem/logs', element: <PermissionGuard permission={P.SIEM_SYSLOG_VIEW}><LogExplorerPage /></PermissionGuard> },
      { path: 'siem/network-flow-logs', element: <PermissionGuard permission={P.SIEM_FLOWLOGS_VIEW}><NetworkFlowLogsPage /></PermissionGuard> },
      { path: 'siem/traces', element: <PermissionGuard permission={P.SIEM_TRACES_VIEW}><TracesPage /></PermissionGuard> },
      { path: 'siem/email-security', element: <PermissionGuard permission={P.SIEM_SYSLOG_VIEW}><EmailSecurityPage /></PermissionGuard> },
      { path: 'siem/classifiers', element: <Navigate to="/settings/siem/classifiers" replace /> },

      // Settings
      { path: 'settings/general', element: <PermissionGuard permission={P.SETTINGS_TENANT_VIEW}><GeneralSettingsPage /></PermissionGuard> },
      { path: 'settings/security', element: <PermissionGuard permission={P.SETTINGS_TENANT_VIEW}><SecuritySettingsPage /></PermissionGuard> },
      { path: 'settings/notifications', element: <PermissionGuard permission={P.SETTINGS_TENANT_VIEW}><NotificationSettingsPage /></PermissionGuard> },
      { path: 'settings/branding', element: <PermissionGuard permission={P.SETTINGS_TENANT_VIEW}><BrandingSettingsPage /></PermissionGuard> },
      { path: 'settings/users', element: <PermissionGuard permission={P.SETTINGS_USERS_VIEW}><UserManagementPage /></PermissionGuard> },
      { path: 'settings/api-keys', element: <PermissionGuard permission={[P.AGENT_KEYS_VIEW, P.AGENT_KEYS_MANAGE]}><ApiKeysPage /></PermissionGuard> },
      { path: 'settings/cmdb-config', element: <PermissionGuard permission={[P.CMDB_DEVICE_TYPES_VIEW, P.CMDB_DEVICE_GROUPS_VIEW, P.CMDB_DEVICE_TYPES_MANAGE, P.CMDB_DEVICE_GROUPS_MANAGE]}><CmdbConfigPage /></PermissionGuard> },
      { path: 'settings/device-types', element: <Navigate to="/settings/cmdb-config" replace /> },
      { path: 'settings/device-groups', element: <Navigate to="/settings/cmdb-config" replace /> },
      { path: 'settings/tags', element: <Navigate to="/settings/cmdb-config" replace /> },
      { path: 'settings/alert-rules', element: <Navigate to="/itim/alerting/alert-rules" replace /> },
      { path: 'settings/sites', element: <PermissionGuard permission={[P.CMDB_SITES_VIEW, P.CMDB_SITES_MANAGE]}><SitesPage /></PermissionGuard> },
      { path: 'settings/locations', element: <PermissionGuard permission={[P.CMDB_SITES_VIEW, P.CMDB_SITES_MANAGE]}><SiteLocationsPage /></PermissionGuard> },
      {
        path: 'settings/departments',
        element: <GroupsFlagRedirect legacy={<PermissionGuard permission={[P.SETTINGS_DEPARTMENTS_VIEW, P.SETTINGS_DEPARTMENTS_MANAGE]}><DepartmentManagementPage /></PermissionGuard>} />,
      },
      {
        path: 'settings/user-groups',
        element: <GroupsFlagRedirect legacy={<PermissionGuard permission={P.SETTINGS_USER_GROUPS_VIEW}><UserGroupManagementPage /></PermissionGuard>} />,
      },
      {
        path: 'settings/user-groups/new',
        element: <GroupsFlagRedirect legacy={<PermissionGuard permission={[P.SETTINGS_USER_GROUPS_CREATE, P.SETTINGS_USER_GROUPS_MANAGE]}><UserGroupEditorPage /></PermissionGuard>} />,
      },
      {
        path: 'settings/user-groups/:id',
        element: <GroupsFlagRedirect legacy={<PermissionGuard permission={[P.SETTINGS_USER_GROUPS_EDIT, P.SETTINGS_USER_GROUPS_MANAGE]}><UserGroupEditorPage /></PermissionGuard>} />,
      },
      // Universal Groups — unified workspace superseding user-groups + departments (D1/D2b)
      { path: 'settings/groups', element: <PermissionGuard permission={P.SETTINGS_GROUPS_VIEW}><GroupsWorkspacePage /></PermissionGuard> },
      { path: 'settings/permissions', element: <PermissionGuard permission={P.SETTINGS_USER_GROUPS_VIEW}><PermissionsPage /></PermissionGuard> },
      { path: 'settings/email-templates', element: <Navigate to="/itim/alerting/email-templates" replace /> },
      { path: 'settings/device-credentials', element: <PermissionGuard permission={[P.SETTINGS_DEVICE_CREDENTIALS_VIEW, P.SETTINGS_DEVICE_CREDENTIALS_MANAGE]}><DeviceCredentialsPage /></PermissionGuard> },
      { path: 'settings/credentials', element: <PermissionGuard permission={P.SETTINGS_CREDENTIALS_VIEW}><CredentialsListPage /></PermissionGuard> },
      { path: 'settings/credentials/:id', element: <PermissionGuard permission={P.SETTINGS_CREDENTIALS_VIEW}><CredentialDetailPage /></PermissionGuard> },
      { path: 'settings/snmp-mib-profiles', element: <PermissionGuard permission={[P.SETTINGS_SNMP_MIB_PROFILES_VIEW, P.SETTINGS_SNMP_MIB_PROFILES_MANAGE]}><SnmpMibProfilesPage /></PermissionGuard> },
      { path: 'settings/mib-profile-repos', element: <PermissionGuard permission={[P.SETTINGS_SNMP_MIB_PROFILES_VIEW, P.SETTINGS_SNMP_MIB_PROFILES_MANAGE]}><MibProfileReposPage /></PermissionGuard> },
      { path: 'settings/agent-config', element: <PermissionGuard permission={P.AGENT_AGENTS_MANAGE}><AgentConfigPage /></PermissionGuard> },
      { path: 'settings/siem/classifiers', element: <PermissionGuard permission={P.SIEM_CLASSIFIERS_VIEW}><EventClassifiersPage /></PermissionGuard> },
      { path: 'settings/siem/sources', element: <PermissionGuard permission={P.SIEM_SYSLOG_VIEW}><SyslogSourcesPage /></PermissionGuard> },
      { path: 'settings/import', element: <PermissionGuard permission={P.SETTINGS_IMPORT_CSV}><ImportPage /></PermissionGuard> },
      { path: 'settings/sso', element: <PermissionGuard permission={P.SETTINGS_SSO_VIEW}><TenantSsoPage /></PermissionGuard> },

      // Integrations
      { path: 'integrations', element: <PermissionGuard permission={P.INTEGRATIONS_CONNECTIONS_VIEW}><IntegrationsPage /></PermissionGuard> },

      // Privacy & Compliance — cookie scanner. Both routes guard on
      // web-properties.view; the detail page's tabs additionally gate their own
      // actions on privacy.cookies.edit / privacy.scans.run.
      { path: 'privacy/cookie-scanner', element: <PermissionGuard permission={P.PRIVACY_WEB_PROPERTIES_VIEW}><WebPropertiesPage /></PermissionGuard> },
      { path: 'privacy/cookie-scanner/:id', element: <PermissionGuard permission={P.PRIVACY_WEB_PROPERTIES_VIEW}><WebPropertyDetailPage /></PermissionGuard> },
      { path: 'privacy/triage', element: <PermissionGuard permission={P.PRIVACY_COOKIES_VIEW}><CookieReviewPage /></PermissionGuard> },

      // Domain & Email Security Posture — SPF/DMARC/DKIM/MX monitoring. Both
      // routes guard on domains.view; the detail page's actions additionally
      // gate on posture.checks.run / posture.findings.suppress.
      { path: 'posture/domains', element: <PermissionGuard permission={P.POSTURE_DOMAINS_VIEW}><PostureDomainsPage /></PermissionGuard> },
      { path: 'posture/domains/:id', element: <PermissionGuard permission={P.POSTURE_DOMAINS_VIEW}><PostureDomainDetailPage /></PermissionGuard> },

      // RSS Feeds
      { path: 'feeds', element: <PermissionGuard permission={P.RSS_FEEDS_VIEW}><FeedsPage /></PermissionGuard> },
      { path: 'feeds/new', element: <Navigate to="/feeds?new=1" replace /> },

      // /itkm/files has been replaced by the global Files surface.
      { path: 'itkm/files', element: <Navigate to="/files" replace /> },

      // Centralized Files — global, permission-filtered view across all modules.
      { path: 'files', element: <PermissionGuard permission={P.FILES_READ_GLOBAL}><FilesPage /></PermissionGuard> },

      // ITKM Articles (Phase A2) — slug routes for stable shortlinks
      { path: 'itkm/articles', element: <PermissionGuard permission={P.KB_ARTICLES_VIEW}><KbArticleListPage /></PermissionGuard> },
      { path: 'itkm/articles/new', element: <PermissionGuard permission={P.KB_ARTICLES_CREATE}><KbArticleEditorPage /></PermissionGuard> },
      { path: 'itkm/articles/:slug', element: <PermissionGuard permission={P.KB_ARTICLES_VIEW}><KbArticleDetailPage /></PermissionGuard> },
      { path: 'itkm/articles/:slug/edit', element: <PermissionGuard permission={P.KB_ARTICLES_EDIT}><KbArticleEditorPage /></PermissionGuard> },

      // Automation — Scripts library (ITPA)
      { path: 'automation/scripts', element: <PermissionGuard permission={P.AUTOMATION_SCRIPTS_VIEW}><ScriptsLibraryPage /></PermissionGuard> },
      { path: 'automation/scripts/new', element: <PermissionGuard permission={P.AUTOMATION_SCRIPTS_AUTHOR}><ScriptEditorPage /></PermissionGuard> },
      { path: 'automation/scripts/:id', element: <PermissionGuard permission={P.AUTOMATION_SCRIPTS_VIEW}><ScriptDetailPage /></PermissionGuard> },
      { path: 'automation/scripts/:id/edit', element: <PermissionGuard permission={P.AUTOMATION_SCRIPTS_AUTHOR}><ScriptEditorPage /></PermissionGuard> },
      { path: 'automation/storage-kv', element: <PermissionGuard permission={P.AUTOMATION_KV_VIEW}><StorageKvPage /></PermissionGuard> },

      // Software Deployment (ITKM)
      { path: 'software/catalog', element: <PermissionGuard permission={P.SOFTWARE_CATALOG_VIEW}><SoftwareCatalogPage /></PermissionGuard> },
      { path: 'software/catalog/:id', element: <PermissionGuard permission={P.SOFTWARE_CATALOG_VIEW}><SoftwarePackageDetailPage /></PermissionGuard> },
      { path: 'software/cohorts', element: <PermissionGuard permission={P.SOFTWARE_COHORT_VIEW}><SoftwareCohortsPage /></PermissionGuard> },
      { path: 'software/rollouts', element: <PermissionGuard permission={P.SOFTWARE_ROLLOUT_VIEW}><SoftwareRolloutsPage /></PermissionGuard> },
      { path: 'software/rollouts/:id', element: <PermissionGuard permission={P.SOFTWARE_ROLLOUT_VIEW}><SoftwareTenantRolloutDetailPage /></PermissionGuard> },
      { path: 'software/msp-rollouts/:id', element: <PermissionGuard permission={P.SOFTWARE_ROLLOUT_MSP_ADVANCE}><SoftwareMspRolloutDetailPage /></PermissionGuard> },
      { path: 'software/installs', element: <PermissionGuard permission={P.SOFTWARE_INSTALLS_VIEW}><SoftwareInstallHistoryPage /></PermissionGuard> },

      // PSA / Billing
      { path: 'psa/clients', element: <PermissionGuard permission={P.PSA_CLIENTS_VIEW}><ClientListPage /></PermissionGuard> },
      { path: 'psa/clients/:id', element: <PermissionGuard permission={P.PSA_CLIENTS_VIEW}><ClientDetailPage /></PermissionGuard> },
      { path: 'psa/products', element: <PermissionGuard permission={P.PSA_PRODUCTS_VIEW}><ProductCatalogPage /></PermissionGuard> },
      { path: 'psa/contracts', element: <PermissionGuard permission={P.PSA_CONTRACTS_VIEW}><ContractListPage /></PermissionGuard> },
      { path: 'psa/contracts/:id', element: <PermissionGuard permission={P.PSA_CONTRACTS_VIEW}><ContractDetailPage /></PermissionGuard> },
      { path: 'psa/sows/:id', element: <PermissionGuard permission={P.PSA_CONTRACTS_VIEW}><SowDetailPage /></PermissionGuard> },
      { path: 'psa/invoices', element: <PermissionGuard permission={P.PSA_BILLING_VIEW}><InvoiceListPage /></PermissionGuard> },
      { path: 'psa/time-entries', element: <PermissionGuard permission={P.PSA_TIME_VIEW}><TimeEntryListPage /></PermissionGuard> },

      // Expenses — the report route guards on EXPENSES_MILEAGE_REPORT, not
      // _VIEW: a full tax year of one employee's movements is an explicit
      // grant, not a side effect of holding every `view` verb.
      { path: 'expenses/mileage', element: <PermissionGuard permission={P.EXPENSES_MILEAGE_VIEW}><MileageListPage /></PermissionGuard> },
      { path: 'expenses/vehicles', element: <PermissionGuard permission={P.EXPENSES_MILEAGE_VIEW}><VehicleListPage /></PermissionGuard> },
      { path: 'expenses/mileage-rates', element: <PermissionGuard permission={P.EXPENSES_MILEAGE_VIEW}><MileageRatesPage /></PermissionGuard> },
      { path: 'expenses/mileage-report', element: <PermissionGuard permission={P.EXPENSES_MILEAGE_REPORT}><MileageReportPage /></PermissionGuard> },

      // Unified Contacts
      { path: 'contacts', element: <PermissionGuard permission={P.CONTACTS_CONTACTS_VIEW}><ContactListPage /></PermissionGuard> },
      { path: 'contacts/:id', element: <PermissionGuard permission={P.CONTACTS_CONTACTS_VIEW}><ContactDetailPage /></PermissionGuard> },

      // E-Signature ("Sign")
      { path: 'esign/envelopes', element: <PermissionGuard permission={P.ESIGN_ENVELOPES_VIEW}><EsignEnvelopeListPage /></PermissionGuard> },
      { path: 'esign/envelopes/new', element: <PermissionGuard permission={P.ESIGN_ENVELOPES_CREATE}><EsignEnvelopeNewPage /></PermissionGuard> },
      { path: 'esign/envelopes/:id', element: <PermissionGuard permission={P.ESIGN_ENVELOPES_VIEW}><EsignEnvelopeDetailPage /></PermissionGuard> },

      // Billing Portal (customer-facing)
      { path: 'portal/billing', element: <PermissionGuard permission={P.PORTAL_BILLING_VIEW}><PortalOverviewPage /></PermissionGuard> },
      { path: 'portal/billing/invoices', element: <PermissionGuard permission={P.PORTAL_BILLING_VIEW}><PortalInvoicesPage /></PermissionGuard> },
      { path: 'portal/billing/payment-methods', element: <PermissionGuard permission={P.PORTAL_BILLING_VIEW}><PortalPaymentMethodsPage /></PermissionGuard> },
      { path: 'portal/billing/usage', element: <PermissionGuard permission={P.PORTAL_BILLING_VIEW}><PortalUsagePage /></PermissionGuard> },

      // Reports
      { path: 'reports', element: <PermissionGuard permission={P.REPORTS_VIEW}><ReportsPage /></PermissionGuard> },

      // Changelog (all authenticated users)
      { path: 'changelog', element: <ChangelogPage /> },

      // Developer Tools (granular developer.* permissions — opt-in via the Developers preset)
      { path: 'devtools/data', element: <PermissionGuard permission={P.DEVELOPER_DATA_READ}><DataOverviewPage /></PermissionGuard> },
      { path: 'devtools/redis', element: <PermissionGuard permission={P.DEVELOPER_REDIS_READ}><RedisCacheExplorerPage /></PermissionGuard> },
      { path: 'devtools/health', element: <PermissionGuard permission={P.DEVELOPER_HEALTH_READ}><HealthDashboardPage /></PermissionGuard> },
      { path: 'devtools/api-docs', element: <PermissionGuard permission={P.DEVELOPER_DOCS_READ}><ApiDocumentationPage /></PermissionGuard> },
      { path: 'devtools/environment', element: <PermissionGuard permission={P.DEVELOPER_ENVIRONMENT_READ}><EnvironmentViewerPage /></PermissionGuard> },
      { path: 'devtools/registry', element: <PermissionGuard permission={P.DEVELOPER_REGISTRY_READ}><RegistryViewerPage /></PermissionGuard> },
      { path: 'devtools/jobs', element: <PermissionGuard permission={P.DEVELOPER_JOBS_READ}><JobExplorerPage /></PermissionGuard> },
      { path: 'devtools/satellites', element: <PermissionGuard permission={P.NETWORK_SATELLITE_VIEW}><SatelliteAgentsPage /></PermissionGuard> },
      { path: 'devtools/cron-playground', element: <PermissionGuard permission={P.DEVELOPER_CRON_READ}><CronPlaygroundPage /></PermissionGuard> },
      { path: 'devtools/kv', element: <PermissionGuard permission={P.AUTOMATION_KV_VIEW}><StorageKvExplorerPage /></PermissionGuard> },
      { path: 'permissions', element: <Navigate to="/settings/permissions" replace /> },

      // Scheduled Tasks (tenant)
      { path: 'scheduled-tasks', element: <PermissionGuard permission={P.SCHEDULER_TASKS_VIEW}><ScheduledTasksPage /></PermissionGuard> },
      { path: 'scheduled-tasks/new', element: <PermissionGuard permission={[P.SCHEDULER_TASKS_CREATE, P.SCHEDULER_TASKS_MANAGE]}><NewScheduledTaskPage /></PermissionGuard> },
      { path: 'scheduled-tasks/:id', element: <PermissionGuard permission={P.SCHEDULER_TASKS_VIEW}><ScheduledTaskDetailPage /></PermissionGuard> },

      // Admin (MSP only)
      { path: 'admin/tenants', element: <PermissionGuard permission={[P.ADMIN_TENANTS_VIEW, P.ADMIN_TENANTS_MANAGE]}><TenantManagementPage /></PermissionGuard> },
      { path: 'admin/sso', element: <PermissionGuard permission={[P.ADMIN_SSO_VIEW, P.ADMIN_SSO_MANAGE]}><MspSsoPage /></PermissionGuard> },
      { path: 'admin/system-schedulers', element: <PermissionGuard permission={P.SCHEDULER_SYSTEM_VIEW}><SystemSchedulersPage /></PermissionGuard> },
      { path: 'admin/system-schedulers/:id', element: <PermissionGuard permission={P.SCHEDULER_SYSTEM_VIEW}><SystemSchedulerDetailPage /></PermissionGuard> },
      { path: 'admin/kms', element: <PermissionGuard permission={P.SYSTEM_KMS_VIEW}><KmsAdminPage /></PermissionGuard> },

      // Catch-all 404. Mounted as a normal `element` (not an `errorElement`),
      // so `useRouteError()` inside ErrorPage is null — pass `notFound` so it
      // renders a real 404 instead of a misleading "Something Went Wrong" 500.
      { path: '*', element: <ErrorPage notFound /> },
    ],
  },
]);
