import { useEffect, useRef } from 'react';
import React from 'react';
import { BrowserRouter, Routes, Route, Navigate, useNavigate as useNavigate2, useParams } from 'react-router-dom';
import { useAuthStore } from './store/auth';
import api from './store/api';
import { licenseStore } from './store/license';
import { useRealtimeStore, notifyMarkedScript } from './store/realtime';
import { attachNotificationsRealtime } from './store/notifications';
import { useSchoolSettingsStore } from './store/schoolSettings';
import { verifyLicenseOffline } from './services/offlineLicenseVerifier';
import Login from './pages/Login';
import { LicenseSourceBanner } from './components/LicenseSourceBanner';

// Admin pages
import AdminDashboard from './pages/dashboard/AdminDashboard';
import Reports from './pages/admin/Reports';
import Settings from './pages/admin/Settings';
import Users from './pages/admin/Users';
import UserRoles from './pages/admin/UserRoles';
import Cohorts from './pages/admin/Cohorts';
import CohortDetail from './pages/admin/CohortDetail';
import CohortForm from './components/CohortForm';
import ClassDetail from './pages/admin/ClassDetail';
import Departments from './pages/admin/Departments';
import Students from './pages/Students';
import Teachers from './pages/Teachers';
import Classes from './pages/Classes';
import Attendance from './pages/Attendance';
import Fees from './pages/Fees';
import Messages from './pages/Messages';
import Events from './pages/Events';
import Profile from './pages/Profile';
import Nav from './components/Nav';
//vale
import NoticeBoard from './pages/admin/NoticeBoard';
import Library from './pages/admin/Library';
import Inventory from './pages/admin/Inventory';
import HRManagement from './pages/admin/HRManagement';
import StaffAttendance from './pages/admin/StaffAttendance';
import HostelPortal from './pages/admin/HostelPortal';
import TransportDashboard from './pages/admin/TransportDashboard';
import AuditLogs from './pages/admin/AuditLogs';
import SyncLogs from './pages/admin/SyncLogs';
import StudentExtracurriculars from './pages/student/Extracurriculars';
import TeacherExtracurriculars from './pages/teacher/Extracurriculars';
import AcademicRollover from './pages/admin/AcademicRollover';
import Offboarding from './pages/admin/Offboarding';
import OffboardingWizard from './pages/admin/OffboardingWizard';
import Alumni from './pages/admin/Alumni';

import SysAdminDashboard from './pages/dashboard/SysAdminDashboard';
import AccountantDashboardPage from './pages/dashboard/AccountantDashboard';
import VisitorLog from './pages/admin/front-office/VisitorLog';
import AdmissionEnquiry from './pages/admin/front-office/AdmissionEnquiry';
import Complaints from './pages/admin/front-office/Complaints';
import PhoneCalls from './pages/admin/front-office/PhoneCalls';
import PostalDispatch from './pages/admin/front-office/PostalDispatch';
import LegacyImport from './pages/admin/LegacyImport';

// Librarian pages
import LibrarianDashboard from './pages/librarian/Dashboard';
import LibrarianBooks from './pages/librarian/Books';
import LibrarianIssues from './pages/librarian/Issues';
import LibrarianFines from './pages/librarian/Fines';
import LibrarianReservations from './pages/librarian/Reservations';

// Clubs Head pages
import ClubsHeadDashboard from './pages/clubs_head/Dashboard';
import ClubManagement from './pages/clubs_head/ClubManagement';

// Role-specific dashboards
import TeacherDashboard from './pages/dashboard/TeacherDashboard';
import StudentDashboard from './pages/dashboard/StudentDashboard';
import ParentDashboard from './pages/dashboard/ParentDashboard';
// Note: pages/dashboard/ClubsHeadDashboard is the teacher-extracurriculars view
// (mislocated); the canonical clubs-head dashboard lives at pages/clubs_head/Dashboard.

// New role-aware analytics dashboards (school_admin/systems_admin/teacher/student/parent).
// These consume the extended analytics endpoints from server/src/controllers/dashboard.controller.js
// (active_enrollments / per_course / leaderboard_rank / per_dependent / etc., added in commit 89df1cd).
// Principal, HR, Bursar keep the legacy dashboards at pages/dashboard/AdminDashboard because their
// routes still resolve to the same /dashboard/admin path with role-scoped allowedRoles.
import SchoolAdminDashboard from './pages/admin/AdminDashboard';
import TeacherAnalyticsDashboard from './pages/teacher/TeacherDashboard';
import StudentAnalyticsDashboard from './pages/student/StudentDashboard';
import ParentAnalyticsDashboard from './pages/parent/ParentDashboard';

// Phase 1 — HR & Finance module surfaces (feature/hr-finance-phase-1-frontend).
// HRDashboard / FinanceDashboard are the role landing pages for /dashboard/hr and /dashboard/finance.
// Expenses (list/new/edit) and PayslipView live under /finance and /hr respectively.
import HRDashboard from './pages/dashboard/HRDashboard';
import FinanceDashboard from './pages/dashboard/FinanceDashboard';
import AccountantDashboard from './pages/dashboard/AccountantDashboard';
import ExpensesPage from './pages/finance/Expenses';
import ExpenseEditPage from './pages/finance/ExpenseEdit';
import PayslipViewPage from './pages/hr/PayslipView';

// Sprint 1b — feature/hr-finance-phase-1b
import LeaveApprovalPage from './pages/hr/LeaveApproval';
import StaffDirectoryPage from './pages/hr/StaffDirectory';
import PayrollRunsPage from './pages/finance/PayrollRuns';
import PayslipsPage from './pages/finance/Payslips';

// §10a — Finance Phase 2 operational core (feature/finance-phase-2).
import SuppliersPage from './pages/finance/Suppliers';
import ChartOfAccountsPage from './pages/finance/ChartOfAccounts';
import InvoicesPage from './pages/finance/Invoices';
import TripsPage from './pages/finance/Trips';
import TripDetailPage from './pages/finance/TripDetail';
import BankingAccountsPage from './pages/finance/BankingAccounts';
import BankingReconcilePage from './pages/finance/BankingReconcile';

// §10b — Fee engine surfaces (feature/finance-phase-2b).
import StudentGroupsPage from './pages/finance/StudentGroups';
import StudentGroupDetailPage from './pages/finance/StudentGroupDetail';
import FeePlansPage from './pages/finance/FeePlans';
import DiscountsPage from './pages/finance/Discounts';

// Student pages
import StudentAssignments from './pages/student/Assignments';
import StudentFeesPage from './pages/student/Fees';
import StudentMyCourses from './pages/student/MyCourses';
import StudentGrades from './pages/student/Grades';
import StudentReportCard from './pages/student/ReportCard';
import StudentExams from './pages/student/Exams';
import ExamEditor from './pages/exams/ExamEditor';
import { ExamListPage, TakeExamPage, ExamResultsPage } from './pages/exams/ExamViews';
import ExamReview from './pages/admin/ExamReview';
import StudentMedical from './pages/student/Medical';
// PR 3 §6.2/§6.3 — student Homework, Tests, Resources surfaces.
import StudentHomework from './pages/student/Homework';
import StudentTests from './pages/student/Tests';
import StudentResources from './pages/student/Resources';

// Parent pages (medical)
import ParentMedical from './pages/parent/Medical';

// Student Medical module — feature/student-medical-records
import NurseDashboard from './pages/dashboard/NurseDashboard';
import DiningDashboard from './pages/dashboard/DiningDashboard';
import {
  SanatoriumPortal,
  DiningHall,
  ClassMedicalView,
} from './pages/medical/MedicalViews';

// Next-gen core modules: crossword + enrollment + bulk marks
import { CrosswordPage } from './pages/crossword/CrosswordPage';
import { CrosswordLeaderboardPage } from './pages/crossword/CrosswordLeaderboard';
import { EnrollmentsPage } from './pages/enrollments/EnrollmentsPage';
import { BulkMarksPage } from './pages/marks/BulkMarksPage';

// Teacher pages
import TeacherMyCourses from './pages/teacher/MyCourses';
import TeacherAssignments from './pages/teacher/Assignments';
import TeacherStudents from './pages/teacher/Students';
import { TeacherTools } from './pages/teacher/TeacherTools';
import AttendanceTake from './pages/teacher/AttendanceTake';
import TeacherAttendanceHistory from './pages/teacher/AttendanceHistory';
import TeacherResources from './pages/teacher/Resources';
import TeacherHomework from './pages/teacher/Homework';
import TeacherTests from './pages/teacher/Tests';
// P1-UX-7 — Class Room page (Course Scheme/Plan per UI/UX feedback PDF §9).
import { ClassRoom } from './pages/teacher/ClassRoom';

// Parent pages
import ParentCalendar from './pages/parent/Calendar';
import AcademicProgress from './pages/parent/AcademicProgress';
import ParentAttendance from './pages/parent/Attendance';
import ParentFees from './pages/parent/Fees';
import ParentAttendanceHistory from './pages/parent/AttendanceHistory';
// PR 3 §7.2 — parent Resources surface (per-child subject resources).
import ParentResources from './pages/parent/Resources';

// Phase 1 PR 2: tiny wrapper that mounts the CohortForm modal in "create"
// or "edit" mode. Used by the /admin/cohorts/new and /admin/cohorts/:id/edit
// routes so the modal lifecycle (mount + unmount) is owned by the router.
function CohortFormPage() {
  const navigate = useNavigate2();
  const params = useParams<{ id?: string }>();
  const cohortId = params.id ? Number(params.id) : undefined;
  // Fetch the cohort only in edit mode. List is loaded on demand from
  // the store; for edit we re-fetch by id (cheap, single row).
  const [cohort, setCohort] = React.useState<any | null>(null);
  const [loading, setLoading] = React.useState<boolean>(!!cohortId);

  React.useEffect(() => {
    if (!cohortId) return;
    let cancelled = false;
    setLoading(true);
    api
      .get(`/cohorts/${cohortId}`)
      .then((r) => {
        if (!cancelled) setCohort(r.data);
      })
      .catch(() => {
        if (!cancelled) setCohort(null);
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, [cohortId]);

  if (loading) {
    return <div className="text-center text-text-muted py-12">Loading…</div>;
  }

  return (
    <CohortForm
      cohort={cohort || undefined}
      onClose={() => navigate('/admin/cohorts')}
      onSaved={() => navigate(cohortId ? `/admin/cohorts/${cohortId}` : '/admin/cohorts')}
    />
  );
}

// Protected Route Component
function ProtectedRoute({ children, allowedRoles }: { children: React.ReactNode; allowedRoles?: string[] }) {
  const { token, user } = useAuthStore();

  if (!token) {
    return <Navigate to="/login" replace />;
  }

  // Phase 1 PR 1: check effective_roles (primary + auxiliary) instead of
  // just user.role. This is the only auth-layer change in this PR — every
  // existing route that uses ProtectedRoute now honours auxiliary roles
  // automatically. Falls back to user.role for JWTs predating the feature.
  if (allowedRoles && user) {
    const effective = Array.isArray(user.effective_roles) && user.effective_roles.length > 0
      ? user.effective_roles
      : [user.role];
    if (!allowedRoles.some((r) => effective.includes(r))) {
      const roleRoutes: Record<string, string> = {
        school_admin: '/dashboard/admin',
        systems_admin: '/dashboard/admin',
        principal: '/dashboard/admin',
        hr: '/dashboard/hr',
        bursar: '/dashboard/finance',
        nurse: '/dashboard/nurse',
        dining_staff: '/dashboard/dining',
        teacher: '/dashboard/teacher',
        librarian: '/dashboard/librarian',
        clubs_head: '/dashboard/clubs_head',
        student: '/dashboard/student',
        parent: '/dashboard/parent',
      };
      return <Navigate to={roleRoutes[user.role] || '/dashboard/admin'} replace />;
    }
  }

  return <>{children}</>;
}

// Main App Layout with Navigation
function AppLayout() {
  const { token, user, logout, refreshRoles } = useAuthStore();
  const lastMessagesRef = useRef<Record<string | number, string>>({});
  const isInitialLoadRef = useRef(true);

  // Shapeshift (feature/shapeshift): hydrate the school-wide settings
  // store once per auth session so every page renders with the correct
  // education level on first paint, without each page having to call
  // fetchSettings() on mount.
  useEffect(() => {
    if (!token) return;
    useSchoolSettingsStore.getState().fetchSettings();
  }, [token]);

  // Phase 1 PR 1: re-fetch the JWT and effective_roles once per auth
  // session so a freshly-granted auxiliary role is visible without
  // waiting 7 days for the original JWT to expire. refreshRoles is a
  // no-op when offline, so this is safe in PWA mode.
  useEffect(() => {
    if (!token) return;
    refreshRoles().catch(() => { /* swallow — offline path is a no-op */ });
  }, [token, refreshRoles]);

  // License bootstrap (from origin/dev). On every auth, kick the license
  // store; if the school is unlicensed/invalid, log a warning so we
  // notice in dev. The store itself handles UI gating.
  useEffect(() => {
    if (!token) return;
    const promise = licenseStore.getState().bootstrap({});
    if (promise && typeof (promise as any).then === 'function') {
      (promise as Promise<void>).then(() => {
        const current = licenseStore.getState().status;
        if (current === 'unsupported' || current === 'invalid') {
          console.warn('[license] status:', current, licenseStore.getState().reason);
        }
      }).catch(() => undefined);
    }
  }, [token]);

  // PR 3 §13 follow-up — open the shared realtime WebSocket as long as the
  // user is authenticated. Mounting this at the AppLayout level guarantees
  // the socket stays open for the whole session, regardless of which page
  // is currently mounted. Page-level subscribers add their handlers as
  // needed; closing happens when the user logs out (token cleared).
  useEffect(() => {
    if (!token) return;
    const unsubMarked = useRealtimeStore.getState().subscribe('marked_script:returned', (payload) => {
      // Surface a desktop notification whenever a teacher returns work.
      // Pages opt in by reading from useRealtimeStore directly; this
      // notification is the global fallback.
      const items = payload?.data?.marked_scripts;
      if (Array.isArray(items) && items.length > 0) {
        notifyMarkedScript(
          'Marked script returned',
          `A teacher has returned ${items.length} marked file${items.length === 1 ? '' : 's'}.`
        );
      }
    });
    // Notifications bell: refetch unread counter + inbox on message events.
    const unsubNotifications = attachNotificationsRealtime();
    return () => {
      unsubMarked();
      unsubNotifications();
    };
  }, [token]);

  // Request notifications permission
  useEffect(() => {
    if (token && typeof window !== 'undefined' && 'Notification' in window) {
      if (Notification.permission === 'default') {
        Notification.requestPermission();
      }
    }
  }, [token]);

  // Global messages polling for desktop notifications
  useEffect(() => {
    if (!token || !user) return;

    const pollMessages = async () => {
      try {
        const res = await api.get('/messages/conversations');
        const conversations = res.data;

        if (!isInitialLoadRef.current && typeof window !== 'undefined' && 'Notification' in window && Notification.permission === 'granted') {
          conversations.forEach((conv: any) => {
            const prevMsg = lastMessagesRef.current[conv.other_user_id];
            
            // If the message has changed and it was NOT sent by the current user
            if (prevMsg !== undefined && prevMsg !== conv.last_message && conv.last_sender_id !== user.id) {
              // Only notify if we are NOT on the messages page or if the document is hidden/backgrounded
              const isCurrentlyChatingThisPerson = window.location.pathname.startsWith('/messages');
              if (!isCurrentlyChatingThisPerson || document.visibilityState !== 'visible') {
                new Notification(conv.other_user_name, {
                  body: conv.last_message,
                  icon: '/logo.svg'
                });
              }
            }
          });
        }

        // Update ref
        const mapping: Record<string | number, string> = {};
        conversations.forEach((c: any) => {
          mapping[c.other_user_id] = c.last_message;
        });
        lastMessagesRef.current = mapping;
        isInitialLoadRef.current = false;
      } catch (err) {
        console.error('Failed to poll global messages for notifications', err);
      }
    };

    // Initial check
    pollMessages();

    // Poll every 10 seconds
    const interval = setInterval(pollMessages, 10000);
    return () => {
      clearInterval(interval);
      isInitialLoadRef.current = true;
      lastMessagesRef.current = {};
    };
  }, [token, user]);
  
  if (!token) {
    return (
      <Routes>
        <Route path="/login" element={<Login />} />
        <Route path="*" element={<Navigate to="/login" />} />
      </Routes>
    );
  }
  
  const getDashboardRoute = () => {
    if (!user) return '/dashboard/admin';
    const routes: Record<string, string> = {
      school_admin: '/dashboard/admin',
      systems_admin: '/dashboard/admin',
      principal: '/dashboard/admin',
      hr: '/dashboard/hr',
      bursar: '/dashboard/finance',
      nurse: '/dashboard/nurse',
      dining_staff: '/dashboard/dining',
      teacher: '/dashboard/teacher',
      librarian: '/dashboard/librarian',
      clubs_head: '/dashboard/clubs_head',
      student: '/dashboard/student',
      parent: '/dashboard/parent',
    };
    return routes[user.role] || '/dashboard/admin';
  };
  
  const getRoutes = () => {
    if (!user) return [];
    
    const commonRoles = ['systems_admin', 'school_admin', 'teacher', 'student', 'parent', 'principal', 'hr', 'bursar', 'librarian', 'clubs_head', 'nurse', 'dining_staff'];

    // Routes available to EVERYONE authenticated
    const sharedRoutes = [
      { path: '/profile', element: <Profile />, roles: commonRoles },
      { path: '/messages', element: <Messages />, roles: commonRoles },
      { path: '/events', element: <Events />, roles: commonRoles },
      { path: '/notice-board', element: <NoticeBoard />, roles: commonRoles },
      // Enrollments: students see own + request; admin/teacher see pending + approve/reject.
      // The component branches internally based on user.role.
      { path: '/enrollments', element: <EnrollmentsPage />, roles: commonRoles },
      { path: '/admin/offboarding', element: <Offboarding />, roles: ['school_admin', 'systems_admin', 'principal', 'hr'] },
      { path: '/admin/offboarding/wizard/:userId', element: <OffboardingWizard />, roles: ['school_admin', 'systems_admin', 'principal'] },
      { path: '/admin/alumni', element: <Alumni />, roles: ['school_admin', 'systems_admin', 'principal'] },
    ];
    
    switch (user.role) {
      case 'school_admin':
        return [
          { path: '/dashboard/admin', element: <SchoolAdminDashboard />, roles: ['school_admin'] },
          // Phase 1 — HR & Finance module surfaces
          { path: '/dashboard/hr', element: <HRDashboard />, roles: ['school_admin','systems_admin','principal','hr','bursar','accountant'] },
          { path: '/dashboard/finance', element: <FinanceDashboard />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/expenses', element: <ExpensesPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/expenses/new', element: <Navigate to="/finance/expenses" replace />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/expenses/:id/edit', element: <ExpenseEditPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/hr/payslips/:id', element: <PayslipViewPage />, roles: ['school_admin','systems_admin','principal','hr','bursar','accountant'] },
          // Sprint 1b
          { path: '/hr/leave-approval', element: <LeaveApprovalPage />, roles: ['school_admin','systems_admin','principal','hr'] },
          { path: '/hr/staff', element: <StaffDirectoryPage />, roles: ['school_admin','systems_admin','principal','hr'] },
          { path: '/finance/payroll/runs', element: <PayrollRunsPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/payslips', element: <PayslipsPage />, roles: ['school_admin','systems_admin','principal','hr','bursar','accountant'] },
          // §10a — Finance Phase 2 operational core
          { path: '/finance/suppliers', element: <SuppliersPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/chart-of-accounts', element: <ChartOfAccountsPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/invoices', element: <InvoicesPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/trips', element: <TripsPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/trips/:uid', element: <TripDetailPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/banking', element: <BankingAccountsPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/banking/reconcile/new', element: <BankingReconcilePage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/banking/reconciliations/:uid', element: <BankingReconcilePage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          // §10b — Fee engine
          { path: '/finance/groups', element: <StudentGroupsPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/groups/:uid', element: <StudentGroupDetailPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/plans', element: <FeePlansPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/discounts', element: <DiscountsPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/users', element: <Users />, roles: ['school_admin'] },
          // Phase 1 PR 1: auxiliary role management page
          { path: '/admin/user-roles', element: <UserRoles />, roles: ['school_admin','systems_admin'] },
          // Phase 2: FR-SMS3 Legacy CSV Data Import Wizard
          { path: '/admin/legacy-import', element: <LegacyImport />, roles: ['school_admin','systems_admin','principal'] },
          // Phase 1 PR 2: student cohorts (admin can manage; principal can read)
          { path: '/admin/cohorts', element: <Cohorts />, roles: ['school_admin','systems_admin','principal'] },
          { path: '/admin/cohorts/new', element: <CohortFormPage />, roles: ['school_admin','systems_admin'] },
          { path: '/admin/cohorts/:id', element: <CohortDetail />, roles: ['school_admin','systems_admin','principal'] },
          { path: '/admin/cohorts/:id/edit', element: <CohortFormPage />, roles: ['school_admin','systems_admin'] },
          { path: '/students', element: <Students />, roles: ['school_admin'] },
          { path: '/teachers', element: <Teachers />, roles: ['school_admin'] },
          // Phase 1 PR 3: class detail (5 tabs: Overview / Roster / Teachers / Subjects / Cohorts)
          { path: '/admin/classes/:id', element: <ClassDetail />, roles: ['school_admin','systems_admin','principal'] },
          { path: '/classes', element: <Classes />, roles: ['school_admin'] },
          { path: '/attendance', element: <Attendance />, roles: ['school_admin'] },
          { path: '/departments', element: <Departments />, roles: ['school_admin'] },
          { path: '/reports', element: <Reports />, roles: ['school_admin'] },
          { path: '/fees', element: <Fees />, roles: ['school_admin'] },
          { path: '/settings', element: <Settings />, roles: ['school_admin'] },
          { path: '/library', element: <Library />, roles: ['school_admin'] },
          { path: '/inventory', element: <Inventory />, roles: ['school_admin'] },
          { path: '/hr/management', element: <HRManagement />, roles: ['school_admin'] },
          { path: '/hr/attendance', element: <StaffAttendance />, roles: ['school_admin'] },
          { path: '/hostels', element: <HostelPortal />, roles: ['school_admin'] },
          { path: '/transport', element: <TransportDashboard />, roles: ['school_admin'] },
          { path: '/front-office/visitors', element: <VisitorLog />, roles: ['school_admin'] },
          { path: '/front-office/enquiries', element: <AdmissionEnquiry />, roles: ['school_admin'] },
          { path: '/front-office/complaints', element: <Complaints />, roles: ['school_admin'] },
          { path: '/front-office/phone-calls', element: <PhoneCalls />, roles: ['school_admin'] },
          { path: '/front-office/postal', element: <PostalDispatch />, roles: ['school_admin'] },
          { path: '/attendance/take', element: <AttendanceTake />, roles: ['school_admin'] },
          { path: '/attendance/history', element: <TeacherAttendanceHistory />, roles: ['school_admin'] },
          { path: '/admin/academic-rollover', element: <AcademicRollover />, roles: ['school_admin'] },
          { path: '/marks/bulk', element: <BulkMarksPage />, roles: ['school_admin'] },
          { path: '/extracurriculars', element: <TeacherExtracurriculars />, roles: ['school_admin'] },
          // Student medical — supervisor routes (sanatorium access & kitchen roster)
          { path: '/sanatorium', element: <SanatoriumPortal />, roles: ['school_admin'] },
          { path: '/dining-hall', element: <DiningHall />, roles: ['school_admin'] },
          // Exam review workflow — admin/principal queue
          { path: '/exams/review', element: <ExamReview />, roles: ['school_admin'] },
          ...sharedRoutes,
        ];

      case 'systems_admin':
        return [
          { path: '/dashboard/admin', element: <SysAdminDashboard />, roles: ['systems_admin'] },
          { path: '/dashboard/accountant', element: <AccountantDashboard />, roles: ['school_admin','principal','bursar','accountant'] },
          // Phase 1 — HR & Finance module surfaces
          { path: '/dashboard/hr', element: <HRDashboard />, roles: ['school_admin','systems_admin','principal','hr','bursar','accountant'] },
          { path: '/dashboard/finance', element: <FinanceDashboard />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/expenses', element: <ExpensesPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/expenses/new', element: <Navigate to="/finance/expenses" replace />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/expenses/:id/edit', element: <ExpenseEditPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/hr/payslips/:id', element: <PayslipViewPage />, roles: ['school_admin','systems_admin','principal','hr','bursar','accountant'] },
          // Sprint 1b
          { path: '/hr/leave-approval', element: <LeaveApprovalPage />, roles: ['school_admin','systems_admin','principal','hr'] },
          { path: '/hr/staff', element: <StaffDirectoryPage />, roles: ['school_admin','systems_admin','principal','hr'] },
          { path: '/finance/payroll/runs', element: <PayrollRunsPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/payslips', element: <PayslipsPage />, roles: ['school_admin','systems_admin','principal','hr','bursar','accountant'] },
          // §10a — Finance Phase 2 operational core
          { path: '/finance/suppliers', element: <SuppliersPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/chart-of-accounts', element: <ChartOfAccountsPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/invoices', element: <InvoicesPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/trips', element: <TripsPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/trips/:uid', element: <TripDetailPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/banking', element: <BankingAccountsPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/banking/reconcile/new', element: <BankingReconcilePage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/banking/reconciliations/:uid', element: <BankingReconcilePage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          // §10b — Fee engine
          { path: '/finance/groups', element: <StudentGroupsPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/groups/:uid', element: <StudentGroupDetailPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/plans', element: <FeePlansPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/discounts', element: <DiscountsPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/users', element: <Users />, roles: ['systems_admin'] },
          // Phase 1 PR 1: auxiliary role management page
          { path: '/admin/user-roles', element: <UserRoles />, roles: ['school_admin','systems_admin'] },
          // Phase 1 PR 2: student cohorts (admin can manage; principal can read)
          { path: '/admin/cohorts', element: <Cohorts />, roles: ['school_admin','systems_admin','principal'] },
          { path: '/admin/cohorts/new', element: <CohortFormPage />, roles: ['school_admin','systems_admin'] },
          { path: '/admin/cohorts/:id', element: <CohortDetail />, roles: ['school_admin','systems_admin','principal'] },
          { path: '/admin/cohorts/:id/edit', element: <CohortFormPage />, roles: ['school_admin','systems_admin'] },
          // Phase 1 PR 3: class detail (read-only for systems_admin in this PR)
          { path: '/admin/classes/:id', element: <ClassDetail />, roles: ['school_admin','systems_admin','principal'] },
          { path: '/settings', element: <Settings />, roles: ['systems_admin'] },
          { path: '/audit-logs', element: <AuditLogs />, roles: ['systems_admin'] },
          { path: '/sync-logs', element: <SyncLogs />, roles: ['systems_admin'] },
          { path: '/departments', element: <Departments />, roles: ['systems_admin'] },
          { path: '/reports', element: <Reports />, roles: ['systems_admin'] },
          { path: '/fees', element: <Fees />, roles: ['systems_admin'] },
          { path: '/front-office/visitors', element: <VisitorLog />, roles: ['systems_admin'] },
          { path: '/front-office/enquiries', element: <AdmissionEnquiry />, roles: ['systems_admin'] },
          { path: '/front-office/complaints', element: <Complaints />, roles: ['systems_admin'] },
          { path: '/front-office/phone-calls', element: <PhoneCalls />, roles: ['systems_admin'] },
          { path: '/front-office/postal', element: <PostalDispatch />, roles: ['systems_admin'] },
          { path: '/hr/attendance', element: <StaffAttendance />, roles: ['systems_admin'] },
          { path: '/attendance/take', element: <AttendanceTake />, roles: ['systems_admin'] },
          { path: '/attendance/history', element: <TeacherAttendanceHistory />, roles: ['systems_admin'] },
          { path: '/admin/academic-rollover', element: <AcademicRollover />, roles: ['systems_admin'] },
          { path: '/marks/bulk', element: <BulkMarksPage />, roles: ['systems_admin'] },
          { path: '/sanatorium', element: <SanatoriumPortal />, roles: ['systems_admin'] },
          { path: '/dining-hall', element: <DiningHall />, roles: ['systems_admin'] },
          { path: '/extracurriculars', element: <TeacherExtracurriculars />, roles: ['systems_admin'] },
          // Exam review workflow — admin/principal queue
          { path: '/exams/review', element: <ExamReview />, roles: ['systems_admin'] },
          ...sharedRoutes,
        ];

      case 'principal':
        return [
          { path: '/dashboard/admin', element: <AdminDashboard />, roles: ['principal'] },
          { path: '/dashboard/accountant', element: <AccountantDashboard />, roles: ['school_admin','principal','bursar','accountant'] },
          // Phase 1 — HR & Finance module surfaces
          { path: '/dashboard/hr', element: <HRDashboard />, roles: ['school_admin','systems_admin','principal','hr','bursar','accountant'] },
          { path: '/dashboard/finance', element: <FinanceDashboard />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/expenses', element: <ExpensesPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/expenses/new', element: <Navigate to="/finance/expenses" replace />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/expenses/:id/edit', element: <ExpenseEditPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/hr/payslips/:id', element: <PayslipViewPage />, roles: ['school_admin','systems_admin','principal','hr','bursar','accountant'] },
          // Sprint 1b
          { path: '/hr/leave-approval', element: <LeaveApprovalPage />, roles: ['school_admin','systems_admin','principal','hr'] },
          { path: '/hr/staff', element: <StaffDirectoryPage />, roles: ['school_admin','systems_admin','principal','hr'] },
          { path: '/finance/payroll/runs', element: <PayrollRunsPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/payslips', element: <PayslipsPage />, roles: ['school_admin','systems_admin','principal','hr','bursar','accountant'] },
          // §10a — Finance Phase 2 operational core
          { path: '/finance/suppliers', element: <SuppliersPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/chart-of-accounts', element: <ChartOfAccountsPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/invoices', element: <InvoicesPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/trips', element: <TripsPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/trips/:uid', element: <TripDetailPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/banking', element: <BankingAccountsPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/banking/reconcile/new', element: <BankingReconcilePage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/banking/reconciliations/:uid', element: <BankingReconcilePage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          // §10b — Fee engine
          { path: '/finance/groups', element: <StudentGroupsPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/groups/:uid', element: <StudentGroupDetailPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/plans', element: <FeePlansPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/finance/discounts', element: <DiscountsPage />, roles: ['school_admin','systems_admin','principal','bursar','accountant'] },
          { path: '/users', element: <Users />, roles: ['principal'] },
          // Phase 1 PR 1: principal can list users' role grants (read-only,
          // see the API) but the management UI is admin-only this round.
          // Phase 1 PR 2: cohorts (read-only for principal — no /new or /edit
          // routes mounted; the page itself hides New/Edit buttons).
          { path: '/admin/cohorts', element: <Cohorts />, roles: ['school_admin','systems_admin','principal'] },
          { path: '/admin/cohorts/:id', element: <CohortDetail />, roles: ['school_admin','systems_admin','principal'] },
          // Phase 1 PR 3: class detail (principal is read-only)
          { path: '/admin/classes/:id', element: <ClassDetail />, roles: ['school_admin','systems_admin','principal'] },
          { path: '/students', element: <Students />, roles: ['principal'] },
          { path: '/teachers', element: <Teachers />, roles: ['principal'] },
          { path: '/classes', element: <Classes />, roles: ['principal'] },
          { path: '/attendance', element: <Attendance />, roles: ['principal'] },
          { path: '/departments', element: <Departments />, roles: ['principal'] },
          { path: '/reports', element: <Reports />, roles: ['principal'] },
          { path: '/teacher-tools', element: <TeacherTools />, roles: ['principal'] },
          { path: '/class-room', element: <ClassRoom />, roles: ['principal'] },
          { path: '/fees', element: <Fees />, roles: ['principal'] },
          { path: '/library', element: <Library />, roles: ['principal'] },
          { path: '/inventory', element: <Inventory />, roles: ['principal'] },
          { path: '/hr/management', element: <HRManagement />, roles: ['principal'] },
          { path: '/hr/attendance', element: <StaffAttendance />, roles: ['principal'] },
          { path: '/hostels', element: <HostelPortal />, roles: ['principal'] },
          { path: '/transport', element: <TransportDashboard />, roles: ['principal'] },
          { path: '/front-office/phone-calls', element: <PhoneCalls />, roles: ['principal'] },
          { path: '/front-office/postal', element: <PostalDispatch />, roles: ['principal'] },
          { path: '/attendance/take', element: <AttendanceTake />, roles: ['principal'] },
          { path: '/attendance/history', element: <TeacherAttendanceHistory />, roles: ['principal'] },
          { path: '/marks/bulk', element: <BulkMarksPage />, roles: ['principal'] },
          // Student medical — supervisor routes
          { path: '/sanatorium', element: <SanatoriumPortal />, roles: ['principal'] },
          { path: '/dining-hall', element: <DiningHall />, roles: ['principal'] },
          { path: '/extracurriculars', element: <TeacherExtracurriculars />, roles: ['principal'] },
          // Exam review workflow — admin/principal queue
          { path: '/exams/review', element: <ExamReview />, roles: ['principal'] },
          ...sharedRoutes,
        ];

      case 'hr':
        return [
          { path: '/dashboard/hr', element: <HRDashboard />, roles: ['hr'] },
          { path: '/hr/management', element: <HRManagement />, roles: ['hr'] },
          { path: '/hr/attendance', element: <StaffAttendance />, roles: ['hr'] },
          // Phase 1 — Payslip detail (HR's view into payroll data)
          { path: '/hr/payslips/:id', element: <PayslipViewPage />, roles: ['school_admin','systems_admin','principal','hr','bursar','accountant'] },
          // Sprint 1b
          { path: '/hr/leave-approval', element: <LeaveApprovalPage />, roles: ['school_admin','systems_admin','principal','hr'] },
          { path: '/hr/staff', element: <StaffDirectoryPage />, roles: ['school_admin','systems_admin','principal','hr'] },
          { path: '/finance/payslips', element: <PayslipsPage />, roles: ['school_admin','systems_admin','principal','hr','bursar','accountant'] },
          { path: '/extracurriculars', element: <TeacherExtracurriculars />, roles: ['hr'] },
          { path: '/reports', element: <Reports />, roles: ['hr'] },
          ...sharedRoutes,
        ];

      case 'bursar':
        return [
          { path: '/dashboard/finance', element: <FinanceDashboard />, roles: ['bursar'] },
          { path: '/finance/expenses', element: <ExpensesPage />, roles: ['bursar'] },
          { path: '/finance/expenses/new', element: <Navigate to="/finance/expenses" replace />, roles: ['bursar'] },
          { path: '/finance/expenses/:id/edit', element: <ExpenseEditPage />, roles: ['bursar'] },
          { path: '/hr/payslips/:id', element: <PayslipViewPage />, roles: ['bursar'] },
          { path: '/finance/payroll/runs', element: <PayrollRunsPage />, roles: ['bursar'] },
          { path: '/finance/payslips', element: <PayslipsPage />, roles: ['bursar'] },
          // §10a — Finance Phase 2 operational core
          { path: '/finance/suppliers', element: <SuppliersPage />, roles: ['bursar'] },
          { path: '/finance/chart-of-accounts', element: <ChartOfAccountsPage />, roles: ['bursar'] },
          { path: '/finance/invoices', element: <InvoicesPage />, roles: ['bursar'] },
          { path: '/finance/trips', element: <TripsPage />, roles: ['bursar'] },
          { path: '/finance/trips/:uid', element: <TripDetailPage />, roles: ['bursar'] },
          { path: '/finance/banking', element: <BankingAccountsPage />, roles: ['bursar'] },
          { path: '/finance/banking/reconcile/new', element: <BankingReconcilePage />, roles: ['bursar'] },
          { path: '/finance/banking/reconciliations/:uid', element: <BankingReconcilePage />, roles: ['bursar'] },
          { path: '/inventory', element: <Inventory />, roles: ['bursar'] },
          { path: '/fees', element: <Fees />, roles: ['bursar'] },
          { path: '/reports', element: <Reports />, roles: ['bursar'] },
          // §10b — Fee engine
          { path: '/finance/groups', element: <StudentGroupsPage />, roles: ['bursar'] },
          { path: '/finance/groups/:uid', element: <StudentGroupDetailPage />, roles: ['bursar'] },
          { path: '/finance/plans', element: <FeePlansPage />, roles: ['bursar'] },
          { path: '/finance/discounts', element: <DiscountsPage />, roles: ['bursar'] },
          { path: '/extracurriculars', element: <TeacherExtracurriculars />, roles: ['bursar'] },
          ...sharedRoutes,
        ];

      case 'parent':
        return [
            { path: '/dashboard/parent', element: <ParentAnalyticsDashboard />, roles: ['parent'] },
            { path: '/fees', element: <ParentFees />, roles: ['parent'] },
            { path: '/calendar', element: <ParentCalendar />, roles: ['parent'] },
            { path: '/academic-progress', element: <AcademicProgress />, roles: ['parent'] },
            // Shared report-card route — AcademicProgress opens the same
            // /student/report-card component in a popup with
            // ?child_id=<id>. The component reads child_id to fetch
            // /api/students/:id/report-card instead of /me/report-card.
            { path: '/student/report-card', element: <StudentReportCard />, roles: ['parent'] },
            { path: '/attendance', element: <ParentAttendance />, roles: ['parent'] },
            { path: '/attendance/history', element: <ParentAttendanceHistory />, roles: ['parent'] },
            { path: '/extracurriculars', element: <StudentExtracurriculars />, roles: ['parent'] },
            // Student medical — parent's child record (read + edit)
            { path: '/medical', element: <ParentMedical />, roles: ['parent'] },
            // PR 3 §7.2 — per-child subject resources viewer
            { path: '/parent/resources', element: <ParentResources />, roles: ['parent'] },
          ...sharedRoutes,
        ];

      case 'librarian':
        return [
          { path: '/dashboard/librarian', element: <LibrarianDashboard />, roles: ['librarian'] },
          { path: '/library/books', element: <LibrarianBooks />, roles: ['librarian'] },
          { path: '/library/issues', element: <LibrarianIssues />, roles: ['librarian'] },
          { path: '/library/fines', element: <LibrarianFines />, roles: ['librarian'] },
          { path: '/library/reservations', element: <LibrarianReservations />, roles: ['librarian'] },
          { path: '/extracurriculars', element: <TeacherExtracurriculars />, roles: ['librarian'] },
          ...sharedRoutes,
        ];
      
      case 'teacher':
        return [
          { path: '/dashboard/teacher', element: <TeacherAnalyticsDashboard />, roles: ['teacher'] },
          { path: '/classes', element: <Classes />, roles: ['teacher'] },
          { path: '/attendance', element: <Attendance />, roles: ['teacher'] },
          { path: '/my-courses', element: <TeacherMyCourses />, roles: ['teacher'] },
          { path: '/assignments', element: <TeacherAssignments />, roles: ['teacher'] },
          { path: '/homework', element: <TeacherHomework />, roles: ['teacher','school_admin','systems_admin','principal'] },
          { path: '/tests', element: <TeacherTests />, roles: ['teacher','school_admin','systems_admin','principal'] },
          { path: '/resources', element: <TeacherResources />, roles: ['teacher','school_admin','systems_admin','principal'] },
          { path: '/students', element: <TeacherStudents />, roles: ['teacher'] },
          { path: '/teacher-tools', element: <TeacherTools />, roles: ['teacher'] },
          { path: '/class-room', element: <ClassRoom />, roles: ['teacher'] },
          { path: '/exams/manage', element: <ExamListPage />, roles: ['teacher', 'school_admin', 'systems_admin', 'principal'] },
          { path: '/exams/edit/:id', element: <ExamEditor />, roles: ['teacher'] },
          // ADDED: NoticeBoard for teacher
          { path: '/notice-board', element: <NoticeBoard />, roles: ['teacher'] },
          // ADDED: Extracurriculars (shared with clubs_head)
          { path: '/extracurriculars', element: <TeacherExtracurriculars />, roles: ['teacher', 'clubs_head'] },
          { path: '/extracurriculars', element: <TeacherExtracurriculars />, roles: ['teacher'] },
          { path: '/front-office/visitors', element: <VisitorLog />, roles: ['teacher'] },
          { path: '/front-office/enquiries', element: <AdmissionEnquiry />, roles: ['teacher'] },
          { path: '/front-office/complaints', element: <Complaints />, roles: ['teacher'] },
          { path: '/front-office/phone-calls', element: <PhoneCalls />, roles: ['teacher'] },
          { path: '/front-office/postal', element: <PostalDispatch />, roles: ['teacher'] },
          { path: '/attendance/take', element: <AttendanceTake />, roles: ['teacher'] },
          { path: '/attendance/history', element: <TeacherAttendanceHistory />, roles: ['teacher'] },
          { path: '/marks/bulk', element: <BulkMarksPage />, roles: ['teacher'] },
          // Student medical — class-level emergency flags
          { path: '/medical', element: <ClassMedicalView />, roles: ['teacher'] },
          { path: '/medical/class/:classId', element: <ClassMedicalView />, roles: ['teacher'] },
          ...sharedRoutes,
        ];
      
      case 'student':
        return [
          { path: '/dashboard/student', element: <StudentAnalyticsDashboard />, roles: ['student'] },
          { path: '/my-courses', element: <StudentMyCourses />, roles: ['student'] },
          { path: '/assignments', element: <StudentAssignments />, roles: ['student'] },
          { path: '/exams', element: <StudentExams />, roles: ['student'] },
          { path: '/exams/take', element: <TakeExamPage />, roles: ['student'] },
          { path: '/exams/results', element: <ExamResultsPage />, roles: ['student'] },
          { path: '/grades', element: <StudentGrades />, roles: ['student'] },
          { path: '/student/report-card', element: <StudentReportCard />, roles: ['student', 'parent'] },
          { path: '/attendance', element: <Attendance />, roles: ['student'] },
          // §10c — student fees portal (uses /api/students/:uid/fees).
          { path: '/student/fees', element: <StudentFeesPage />, roles: ['student'] },
          { path: '/fees', element: <StudentFeesPage />, roles: ['student'] },
          { path: '/medical', element: <StudentMedical />, roles: ['student'] },
          { path: '/extracurriculars', element: <StudentExtracurriculars />, roles: ['student'] },
          // PR 3 §6.2 — Homework + Tests mirrors (read-only with submit/marked-script view).
          // Admins/school_admin/systems_admin/principal inherit the same paths for
          // support / inspection (per cleanup PR widening).
          { path: '/homework', element: <StudentHomework />, roles: ['student','school_admin','systems_admin','principal'] },
          { path: '/tests', element: <StudentTests />, roles: ['student','school_admin','systems_admin','principal'] },
          // PR 3 §6.3 — student Resources (enrolled subjects only).
          { path: '/resources', element: <StudentResources />, roles: ['student','school_admin','systems_admin','principal'] },
          ...sharedRoutes,
        ];

      case 'clubs_head':
        return [
          { path: '/dashboard/clubs_head', element: <ClubsHeadDashboard />, roles: ['clubs_head'] },
          { path: '/clubs-management', element: <ClubManagement />, roles: ['clubs_head'] },
          { path: '/extracurriculars', element: <TeacherExtracurriculars />, roles: ['clubs_head'] },
          ...sharedRoutes,
        ];

      // Student Medical module — feature/student-medical-records
      case 'nurse':
        return [
          { path: '/dashboard/nurse', element: <NurseDashboard />, roles: ['nurse'] },
          { path: '/sanatorium', element: <SanatoriumPortal />, roles: ['nurse'] },
          { path: '/dining-hall', element: <DiningHall />, roles: ['nurse'] },
          ...sharedRoutes,
        ];

      case 'dining_staff':
        return [
          { path: '/dashboard/dining', element: <DiningDashboard />, roles: ['dining_staff'] },
          { path: '/dining-hall', element: <DiningHall />, roles: ['dining_staff'] },
          ...sharedRoutes,
        ];
      default:
        return [];
    }
  };
  
  const routes = getRoutes();
  const licenseStatus = licenseStore.getState().status;
  const licenseSource = licenseStore.getState().source;

  return (
    <div className="flex min-h-screen bg-background text-text">
      {/* NFR6 — Skip-to-main link. Visually hidden until focused, so a
          keyboard user can bypass the sidebar nav on every page change. */}
      <a
        href="#main-content"
        className="sr-only focus:not-sr-only focus:fixed focus:top-3 focus:left-3 focus:z-[1000] focus:px-4 focus:py-2 focus:rounded-xl focus:bg-primary focus:text-white focus:font-bold focus:shadow-lg focus:outline-none focus:ring-2 focus:ring-primary/40"
      >
        Skip to main content
      </a>

      <Nav user={user} onLogout={logout} />
      <div className="flex-1 flex flex-col min-w-0 lg:pl-64">
        <main
          id="main-content"
          aria-label="Main content"
          tabIndex={-1}
          className="flex-1 px-4 md:px-6 lg:px-8 pt-20 lg:pt-8 pb-24 lg:pb-8 focus:outline-none"
        >
          {/* Show banner globally ONLY when license is in a critical restricted/expired state */}
          {(licenseStatus === 'expired' || licenseStatus === 'missing' || licenseStatus === 'invalid') && (
            <LicenseSourceBanner />
          )}
          <Routes>
            <Route path="/" element={<Navigate to={getDashboardRoute()} />} />

            {routes.map(({ path, element, roles }) => (
              <Route
                key={path}
                path={path}
                element={
                  <ProtectedRoute allowedRoles={roles}>
                    {element}
                  </ProtectedRoute>
                }
              />
            ))}

            <Route path="*" element={<Navigate to={getDashboardRoute()} />} />
          </Routes>
        </main>
      </div>
    </div>
  );
}

export default function App() {
  return (
    <BrowserRouter future={{ v7_startTransition: true, v7_relativeSplatPath: true }}>
      <AppLayout />
    </BrowserRouter>
  );
}