import { lazy, Suspense, useId, type ReactNode } from 'react';
import { Routes, Route, Navigate, useLocation } from 'react-router-dom';
import { useAuth } from '@/hooks/useAuth';
import Layout from '@/components/layout/Layout';
import AppNavigation from '@/components/layout/Sidebar';
import PageTransition from '@/components/PageTransition';
import { ReleaseNotesDialog } from '@/components/ReleaseNotesDialog';
import CommandPalette from '@/components/CommandPalette';
import LoginPage from '@/pages/LoginPage';
import NotFoundPage from '@/pages/NotFoundPage';
import ErrorBoundary from '@/components/ErrorBoundary';
import PageLoader from '@/components/PageLoader';

// TanStack Query
import { QueryClient, QueryClientProvider, QueryCache } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { toast } from 'sonner';

const queryClient = new QueryClient({
  // Global error handling: pages render an inline error on the *initial* load
  // (no data yet), so only surface a toast when a *background refetch* fails
  // while stale data is still shown — otherwise the failure would be silent.
  queryCache: new QueryCache({
    onError: (error, query) => {
      if (query.state.data !== undefined) {
        toast.error(error?.message || 'Could not refresh — showing the last data.');
      }
    },
  }),
  defaultOptions: {
    queries: {
      staleTime: 1000 * 60 * 2, // 2 minutes
      retry: 1,
      refetchOnWindowFocus: false,
    },
  },
});

// Lazy-loaded components
const AdminPage = lazy(() => import('@/pages/AdminPage'));
const TrackerPage = lazy(() => import('@/pages/TrackerPage'));
const CalendarPage = lazy(() => import('@/pages/CalendarPage'));
const SummaryPage = lazy(() => import('@/pages/SummaryPage'));
const BillsPage = lazy(() => import('@/pages/BillsPage'));
const SubscriptionsPage = lazy(() => import('@/pages/SubscriptionsPage'));
const SubscriptionCatalogPage = lazy(() => import('@/pages/SubscriptionCatalogPage'));
const CategoriesPage = lazy(() => import('@/pages/CategoriesPage'));
const SettingsPage = lazy(() => import('@/pages/SettingsPage'));
const StatusPage = lazy(() => import('@/pages/StatusPage'));
const AnalyticsPage = lazy(() => import('@/pages/AnalyticsPage'));
const ReleaseNotesPage = lazy(() => import('@/pages/ReleaseNotesPage'));
const AboutPage = lazy(() => import('@/pages/AboutPage'));
const PrivacyPage = lazy(() => import('@/pages/PrivacyPage'));
const RoadmapPage = lazy(() => import('@/pages/RoadmapPage'));
const DataPage = lazy(() => import('@/pages/DataPage'));
const ProfilePage = lazy(() => import('@/pages/ProfilePage'));
const SnowballPage = lazy(() => import('@/pages/SnowballPage'));
const HealthPage    = lazy(() => import('@/pages/HealthPage'));
const PayoffPage    = lazy(() => import('@/pages/PayoffPage'));
const SpendingPage  = lazy(() => import('@/pages/SpendingPage'));
const BankTransactionsPage = lazy(() => import('@/pages/BankTransactionsPage'));

function RequireAuth({ children, role }: { children: ReactNode; role?: string }): ReactNode {
  const { user, singleUserMode } = useAuth();
  const location = useLocation();

  // Loading state
  if (user === undefined) {
    return (
      <div className="flex items-center justify-center min-h-screen bg-background text-muted-foreground text-sm">
        Loading...
      </div>
    );
  }

  // Single-user mode bypass
  if (singleUserMode && role === 'user') return children;

  // Not authenticated
  if (!user) {
    return <Navigate to="/login" state={{ from: location }} replace />;
  }

  const roleAllowed = !role || user.role === role || (role === 'user' && user.role === 'admin');

  if (role === 'user' && user.is_default_admin) {
    return <Navigate to="/admin" replace />;
  }

  // Role mismatch
  if (!roleAllowed) {
    return <Navigate to={user.role === 'admin' ? '/admin' : '/'} replace />;
  }

  return children;
}

function AdminShell({ children }: { children: ReactNode }) {
  const location = useLocation();

  return (
    <div className="min-h-screen bg-[radial-gradient(circle_at_top_left,oklch(var(--primary)/0.10),transparent_34rem),linear-gradient(180deg,oklch(var(--background)),oklch(var(--muted)/0.28))] text-foreground">
      <AppNavigation adminMode />
      <main className="mx-auto w-full max-w-[1500px] px-4 py-6 sm:px-6 lg:px-8 lg:py-8">
        <PageTransition routeKey={location.pathname}>
          {children}
        </PageTransition>
      </main>
    </div>
  );
}

export default function App() {
  const { user } = useAuth();
  const mainContentId = useId();

  return (
    <QueryClientProvider client={queryClient}>
      {/* Release notes (only for user role) */}
      {user?.role === 'user' && <ReleaseNotesDialog />}
      {user && !user.is_default_admin && <CommandPalette />}

      {/* Skip link for keyboard users */}
      <a
        href={`#${mainContentId}`}
        className="sr-only focus:not-sr-only focus:fixed focus:top-4 focus:left-4 focus:z-50 focus:bg-background focus:text-foreground focus:px-4 focus:py-2 focus:rounded-md focus:shadow-lg focus:outline-none"
      >
        Skip to main content
      </a>

      <main id={mainContentId}>
        <Routes>
          <Route path="/login" element={<ErrorBoundary><LoginPage /></ErrorBoundary>} />
          <Route path="/about" element={<ErrorBoundary><Suspense fallback={<PageLoader />}><AboutPage /></Suspense></ErrorBoundary>} />
          <Route path="/privacy" element={<ErrorBoundary><Suspense fallback={<PageLoader />}><PrivacyPage /></Suspense></ErrorBoundary>} />
          <Route path="/release-notes" element={<ErrorBoundary><Suspense fallback={<PageLoader />}><ReleaseNotesPage /></Suspense></ErrorBoundary>} />

          <Route
            path="/admin"
            element={
              <RequireAuth role="admin">
                <ErrorBoundary>
                  <Suspense fallback={<PageLoader />}>
                    <AdminPage />
                  </Suspense>
                </ErrorBoundary>
              </RequireAuth>
            }
          />
          <Route
            path="/admin/about"
            element={
              <RequireAuth role="admin">
                <ErrorBoundary>
                  <AdminShell>
                    <Suspense fallback={<PageLoader />}>
                      <AboutPage />
                    </Suspense>
                  </AdminShell>
                </ErrorBoundary>
              </RequireAuth>
            }
          />
          <Route
            path="/roadmap"
            element={
              <RequireAuth role="admin">
                <ErrorBoundary>
                  <AdminShell>
                    <Suspense fallback={<PageLoader />}>
                      <RoadmapPage />
                    </Suspense>
                  </AdminShell>
                </ErrorBoundary>
              </RequireAuth>
            }
          />
          <Route
            path="/admin/roadmap"
            element={
              <RequireAuth role="admin">
                <ErrorBoundary>
                  <AdminShell>
                    <Suspense fallback={<PageLoader />}>
                      <RoadmapPage />
                    </Suspense>
                  </AdminShell>
                </ErrorBoundary>
              </RequireAuth>
            }
          />
          <Route
            path="/admin/status"
            element={
              <RequireAuth role="admin">
                <ErrorBoundary>
                  <AdminShell>
                    <Suspense fallback={<PageLoader />}>
                      <StatusPage />
                    </Suspense>
                  </AdminShell>
                </ErrorBoundary>
              </RequireAuth>
            }
          />
          <Route
            path="/status"
            element={
              <RequireAuth role="admin">
                <Navigate to="/admin/status" replace />
              </RequireAuth>
            }
          />

          <Route
            element={
              <RequireAuth role="user">
                <Layout mainContentId={mainContentId} />
              </RequireAuth>
            }
          >
            <Route index element={<ErrorBoundary><Suspense fallback={<PageLoader />}><TrackerPage /></Suspense></ErrorBoundary>} />
            <Route path="calendar" element={<ErrorBoundary><Suspense fallback={<PageLoader />}><CalendarPage /></Suspense></ErrorBoundary>} />
            <Route path="summary" element={<ErrorBoundary><Suspense fallback={<PageLoader />}><SummaryPage /></Suspense></ErrorBoundary>} />
            <Route path="bills" element={<ErrorBoundary><Suspense fallback={<PageLoader />}><BillsPage /></Suspense></ErrorBoundary>} />
            <Route path="subscriptions" element={<ErrorBoundary><Suspense fallback={<PageLoader />}><SubscriptionsPage /></Suspense></ErrorBoundary>} />
            <Route path="subscriptions/catalog" element={<ErrorBoundary><Suspense fallback={<PageLoader />}><SubscriptionCatalogPage /></Suspense></ErrorBoundary>} />
            <Route path="categories" element={<ErrorBoundary><Suspense fallback={<PageLoader />}><CategoriesPage /></Suspense></ErrorBoundary>} />
            <Route path="health" element={<ErrorBoundary><Suspense fallback={<PageLoader />}><HealthPage /></Suspense></ErrorBoundary>} />
            <Route path="analytics" element={<ErrorBoundary><Suspense fallback={<PageLoader />}><AnalyticsPage /></Suspense></ErrorBoundary>} />
            <Route path="settings" element={<ErrorBoundary><Suspense fallback={<PageLoader />}><SettingsPage /></Suspense></ErrorBoundary>} />
            <Route path="snowball" element={<ErrorBoundary><Suspense fallback={<PageLoader />}><SnowballPage /></Suspense></ErrorBoundary>} />
            <Route path="payoff"   element={<ErrorBoundary><Suspense fallback={<PageLoader />}><PayoffPage /></Suspense></ErrorBoundary>} />
            <Route path="spending" element={<ErrorBoundary><Suspense fallback={<PageLoader />}><SpendingPage /></Suspense></ErrorBoundary>} />
            <Route path="bank-transactions" element={<ErrorBoundary><Suspense fallback={<PageLoader />}><BankTransactionsPage /></Suspense></ErrorBoundary>} />
            <Route path="data" element={<ErrorBoundary><Suspense fallback={<PageLoader />}><DataPage /></Suspense></ErrorBoundary>} />
            <Route path="profile" element={<ErrorBoundary><Suspense fallback={<PageLoader />}><ProfilePage /></Suspense></ErrorBoundary>} />
            <Route path="*" element={<NotFoundPage />} />
          </Route>

          {/* Top-level catch-all — covers public paths that don't exist */}
          <Route path="*" element={<NotFoundPage />} />
        </Routes>
      </main>
      <ReactQueryDevtools initialIsOpen={false} />
    </QueryClientProvider>
  );
}
