import React, { StrictMode, Suspense, lazy, useEffect } from "react";
import type { ProfilerOnRenderCallback } from "react";
import { createRoot } from "react-dom/client";
import { Switch, Route, Redirect, useLocation } from "wouter";
import "./index.css";
import { useIsMobile } from "./hooks/use-mobile";
import { QueryClientProvider } from "@tanstack/react-query";
import { queryClient } from "./lib/queryClient";

import HomePage from "./pages/HomePage";

import { Toaster } from "./components/ui/toaster";
import { useUser } from "./hooks/use-user";
import { Loader2 } from "lucide-react";

// Enhanced retry logic with exponential backoff
const withRetry = <T extends { default: React.ComponentType<any> }>(
  importFn: () => Promise<T>,
  maxRetries = 3
): Promise<T> => {
  return new Promise((resolve, reject) => {
    const attempt = async (attemptsLeft: number) => {
      try {
        const result = await importFn();
        resolve(result);
      } catch (error) {
        if (attemptsLeft === 0) {
          console.error('Module loading failed after all retries:', error);
          reject(error);
        } else {
          const backoffTime = Math.min(1000 * (2 ** (maxRetries - attemptsLeft)), 5000);
          console.warn(`Retrying module load in ${backoffTime}ms. Attempts left: ${attemptsLeft}`);
          setTimeout(() => attempt(attemptsLeft - 1), backoffTime);
        }
      }
    };
    attempt(maxRetries);
  });
};

// Import lazy loading utility
import { lazyWithRetry, preloadComponent } from "./lib/lazyLoad";

// Lazy load components with enhanced error handling
const Calendar = lazyWithRetry(() => import("./pages/Calendar"));
const SharedCalendar = lazyWithRetry(() => import("./pages/SharedCalendar"));
const GroupCalendarPage = lazyWithRetry(() => import("./pages/GroupCalendarPage"));
const Login = lazyWithRetry(() => import("./pages/Login"));
const Home = lazyWithRetry(() => import("./pages/Home"));
const AdminPage = lazyWithRetry(() => import("./pages/AdminPage"));
const AdminSubscriptionsPage = lazyWithRetry(() => import("./pages/AdminSubscriptionsPage"));
const EmailManagementPage = lazyWithRetry(() => import("./pages/EmailManagementPage"));
const CalendarOverview = lazyWithRetry(() => import("./pages/CalendarOverviewPage"));
const MobileCalendar = lazyWithRetry(() => import("./pages/mobile/Calendar"));
const MobileOverview = lazyWithRetry(() => import("./pages/mobile/Overview"));
const MobileGroups = lazyWithRetry(() => import("./pages/mobile/Groups"));
const MobileGroupView = lazyWithRetry(() => import("./pages/mobile/GroupView"));
const MobileSettings = lazyWithRetry(() => import("./pages/mobile/Settings"));
const MobileGroupSettings = lazyWithRetry(() => import("./pages/mobile/GroupSettings"));
const UpgradePage = lazyWithRetry(() => import("./pages/UpgradePage"));
const GroupOverviewPage = lazyWithRetry(() => import("./pages/GroupOverviewPage"));
const GroupPage = lazyWithRetry(() => import("./pages/GroupPage"));
const GroupJoinPage = lazyWithRetry(() => import("./pages/GroupJoinPage"));
const WaitingListPage = lazyWithRetry(() => import("./pages/WaitingListPage"));
const FamilyInvitationPage = lazyWithRetry(() => import("./pages/FamilyInvitationPage"));


// Preload critical routes
const preloadCriticalRoutes = () => {
  preloadComponent(() => import("./pages/Home"));
  preloadComponent(() => import("./pages/Login"));
};

// Start preloading after initial render
if (typeof window !== 'undefined') {
  preloadCriticalRoutes();
}

// Loading component with better UX
const LoadingSpinner = () => (
  <div className="flex items-center justify-center min-h-screen bg-background">
    <div className="text-center">
      <Loader2 className="h-8 w-8 animate-spin mx-auto mb-4" />
      <p className="text-sm text-muted-foreground">Loading...</p>
    </div>
  </div>
);

import { ErrorBoundary } from './components/ErrorBoundary';

function PrivateRoute({ component: Component, requireAdmin = false, ...rest }: any) {
  const { user, isLoading, error } = useUser();

  if (isLoading) {
    return <LoadingSpinner />;
  }

  if (error) {
    return (
      <div className="flex items-center justify-center min-h-screen bg-background">
        <div className="text-center p-6">
          <p className="text-red-500 mb-4">{error.message}</p>
          <button
            className="px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors"
            onClick={() => window.location.href = '/login'}
          >
            Return to Login
          </button>
        </div>
      </div>
    );
  }

  if (!user) {
    return <Redirect to="/login" />;
  }

  if (requireAdmin && !user.is_admin) {
    return <Redirect to="/dashboard" />;
  }

  return <Component {...rest} />;
}

function Router() {
  const isMobile = useIsMobile();
  const [, setLocation] = useLocation();

  useEffect(() => {
    if (isMobile && window.location.pathname === '/dashboard') {
      setLocation('/mobile');
    }
  }, [isMobile, setLocation]);

  return (
    <Switch>
      <Route path="/login">
        <Suspense fallback={<LoadingSpinner />}>
          <Login />
        </Suspense>
      </Route>
      <Route path="/family/invitations">
        <Suspense fallback={<LoadingSpinner />}>
          <FamilyInvitationPage />
        </Suspense>
      </Route>
      <Route path="/">
        <Suspense fallback={<LoadingSpinner />}>
          <Home />
        </Suspense>
      </Route>
      <Route path="/dashboard">
        <Suspense fallback={<LoadingSpinner />}>
          <PrivateRoute component={Calendar} />
        </Suspense>
      </Route>
      <Route path="/admin">
        <Suspense fallback={<LoadingSpinner />}>
          <PrivateRoute component={AdminPage} requireAdmin />
        </Suspense>
      </Route>
      <Route path="/calendar/shared/:shareId">
        <Suspense fallback={<LoadingSpinner />}>
          <SharedCalendar />
        </Suspense>
      </Route>
      <Route path="/overview">
        <Suspense fallback={<LoadingSpinner />}>
          <PrivateRoute component={CalendarOverview} />
        </Suspense>
      </Route>
      <Route path="/mobile">
        <Suspense fallback={<LoadingSpinner />}>
          <PrivateRoute component={MobileCalendar} />
        </Suspense>
      </Route>
      <Route path="/mobile/overview">
        <Suspense fallback={<LoadingSpinner />}>
          <PrivateRoute component={MobileOverview} />
        </Suspense>
      </Route>
      <Route path="/mobile/calendar">
        <Suspense fallback={<LoadingSpinner />}>
          <PrivateRoute component={MobileCalendar} />
        </Suspense>
      </Route>

      <Route path="/groups">
        <Suspense fallback={<LoadingSpinner />}>
          <PrivateRoute component={GroupOverviewPage} />
        </Suspense>
      </Route>
      <Route path="/group/:groupId">
        <Suspense fallback={<LoadingSpinner />}>
          <PrivateRoute component={GroupPage} />
        </Suspense>
      </Route>
      <Route path="/group/join/:shareId">
        <Suspense fallback={<LoadingSpinner />}>
          <GroupJoinPage />
        </Suspense>
      </Route>
      <Route path="/group/:groupId/calendar/:calendarId">
        <Suspense fallback={<LoadingSpinner />}>
          <PrivateRoute component={GroupCalendarPage} />
        </Suspense>
      </Route>
      <Route path="/upgrade">
        <Suspense fallback={<LoadingSpinner />}>
          <UpgradePage />
        </Suspense>
      </Route>
      <Route path="/email-management">
        <Suspense fallback={<LoadingSpinner />}>
          <PrivateRoute component={EmailManagementPage} requireAdmin />
        </Suspense>
      </Route>
      <Route path="/subscriptions">
        <Suspense fallback={<LoadingSpinner />}>
          <PrivateRoute component={AdminSubscriptionsPage} requireAdmin />
        </Suspense>
      </Route>
      <Route path="/waiting-list">
        <Suspense fallback={<LoadingSpinner />}>
          <WaitingListPage />
        </Suspense>
      </Route>
      <Route>
        <div className="flex items-center justify-center min-h-screen bg-background">
          <div className="text-center">
            <h1 className="text-2xl font-bold mb-4">404 - Page Not Found</h1>
            <a href="/" className="text-primary hover:underline">Return Home</a>
          </div>
        </div>
      </Route>
    </Switch>
  );
}

const PerformanceMonitor = React.memo(function PerformanceMonitor({ children }: { children: React.ReactNode }) {
  const SLOW_RENDER_THRESHOLD = 32;

  const onRenderCallback = React.useCallback<ProfilerOnRenderCallback>(
    (id, phase, actualDuration, baseDuration, startTime, commitTime, interactions) => {
      if (actualDuration > SLOW_RENDER_THRESHOLD) {
        console.warn(`Slow render detected in ${id}:`, {
          phase,
          actualDuration: Math.round(actualDuration),
          baseDuration: Math.round(baseDuration),
          interactionCount: interactions?.size || 0,
          timestamp: new Date().toISOString()
        });
      }
    },
    [SLOW_RENDER_THRESHOLD]
  );

  const handleUnhandledRejection = React.useCallback((event: PromiseRejectionEvent) => {
    console.error('Unhandled rejection:', event.reason);
    event.preventDefault();
  }, []);

  const preloadRoutes = React.useCallback(async () => {
    try {
      const routes = [
        import("./pages/Calendar"),
        import("./pages/Home"),
        import("./pages/Login")
      ];

      await Promise.all(routes.map(route => 
        route.catch(err => {
          console.warn('Route preload failed:', err);
          return null;
        })
      ));
    } catch (error) {
      console.error('Error preloading routes:', error);
    }
  }, []);

  React.useEffect(() => {
    preloadRoutes();
    window.addEventListener('unhandledrejection', handleUnhandledRejection);

    return () => {
      window.removeEventListener('unhandledrejection', handleUnhandledRejection);
    };
  }, [handleUnhandledRejection, preloadRoutes]);

  return (
    <React.Profiler id="App" onRender={onRenderCallback}>
      {children}
    </React.Profiler>
  );
});

// Prevent multiple root creation
let root: ReturnType<typeof createRoot> | null = null;
const rootElement = document.getElementById("root");

if (!rootElement) {
  throw new Error("Failed to find the root element");
}

if (!root) {
  root = createRoot(rootElement);
}

root.render(
  <QueryClientProvider client={queryClient}>
    <StrictMode>
      <ErrorBoundary>
        <PerformanceMonitor>
          <Router />
          <Toaster />
        </PerformanceMonitor>
      </ErrorBoundary>
    </StrictMode>
  </QueryClientProvider>
);
