import type { ComponentType } from "react";
import { Navigate, Route, Routes } from "react-router-dom";
import { Suspense, lazy } from "react";

import { AppLayout } from "@/components/layout/AppLayout";
import { useAuthStore } from "@/store/authStore";
import { Spinner } from "./components/ui/spinner";

function lazyNamed<T extends ComponentType<unknown>, TModule extends Record<string, T>>(
  importer: () => Promise<TModule>,
  exportName: keyof TModule,
) {
  return lazy(async () => ({
    default: (await importer())[exportName],
  }));
}

// Lazy load pages
const LoginPage = lazyNamed(() => import("@/pages/LoginPage"), "LoginPage");
const DashboardPage = lazyNamed(() => import("@/pages/DashboardPage"), "DashboardPage");
const ReservationsPage = lazyNamed(() => import("@/pages/ReservationsPage"), "ReservationsPage");
const BookingsPage = lazyNamed(() => import("@/pages/BookingsPage"), "BookingsPage");
const NewBookingPage = lazyNamed(() => import("@/pages/NewBookingPage"), "NewBookingPage");
const BookingDetailPage = lazyNamed(() => import("@/pages/BookingDetailPage"), "BookingDetailPage");
const CalendarPage = lazyNamed(() => import("@/pages/CalendarPage"), "CalendarPage");
const RoomsPage = lazyNamed(() => import("@/pages/RoomsPage"), "RoomsPage");
const GuestServicesPage = lazyNamed(() => import("@/pages/GuestServicesPage"), "GuestServicesPage");
const LoyaltyPointsPage = lazyNamed(() => import("@/pages/LoyaltyPointsPage"), "LoyaltyPointsPage");
const HotelRafflesPage = lazyNamed(() => import("@/pages/HotelRafflesPage"), "HotelRafflesPage");
const CustomersPage = lazyNamed(() => import("@/pages/CustomersPage"), "CustomersPage");
const TransactionsPage = lazyNamed(() => import("@/pages/TransactionsPage"), "TransactionsPage");
const PaymentsPage = lazyNamed(() => import("@/pages/PaymentsPage"), "PaymentsPage");
const VisitsPage = lazyNamed(() => import("@/pages/VisitsPage"), "VisitsPage");
const DiscountCodesPage = lazyNamed(() => import("@/pages/DiscountCodesPage"), "DiscountCodesPage");
const ReferralCodesPage = lazyNamed(() => import("@/pages/ReferralCodesPage"), "ReferralCodesPage");
const ManageUsersPage = lazyNamed(() => import("@/pages/ManageUsersPage"), "ManageUsersPage");
const SettingsPage = lazyNamed(() => import("@/pages/SettingsPage"), "SettingsPage");

function ProtectedLayout() {
  const accessToken = useAuthStore((s) => s.accessToken);
  const bootstrapped = useAuthStore((s) => s.bootstrapped);

  if (!bootstrapped) {
    return (
      <div className="flex min-h-screen items-center justify-center text-muted-foreground">
        <Spinner />
      </div>
    );
  }

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

export default function App() {
  return (
    <Suspense fallback={<div className="p-4">Loading...</div>}>
      <Routes>
        <Route path="/login" element={<LoginPage />} />

        <Route element={<ProtectedLayout />}>
          <Route path="/" element={<Navigate to="/dashboard" replace />} />
          <Route path="/dashboard" element={<DashboardPage />} />
          <Route path="/reservations" element={<ReservationsPage />} />
          <Route path="/bookings" element={<BookingsPage />} />
          <Route path="/bookings/new" element={<NewBookingPage />} />
          <Route path="/bookings/:id" element={<BookingDetailPage />} />
          <Route path="/calendar" element={<CalendarPage />} />
          <Route path="/rooms" element={<RoomsPage />} />
          <Route path="/guest-services" element={<GuestServicesPage />} />
          <Route path="/loyalty/points" element={<LoyaltyPointsPage />} />
          <Route path="/loyalty/raffles" element={<HotelRafflesPage />} />
          <Route path="/customers" element={<CustomersPage />} />
          <Route path="/transactions" element={<TransactionsPage />} />
          <Route path="/payments" element={<PaymentsPage />} />
          <Route path="/marketing/visits" element={<VisitsPage />} />
          <Route path="/marketing/discount-codes" element={<DiscountCodesPage />} />
          <Route path="/marketing/referral-codes" element={<ReferralCodesPage />} />
          <Route path="/settings/users" element={<ManageUsersPage />} />
          <Route path="/settings" element={<SettingsPage />} />
        </Route>

        <Route path="*" element={<Navigate to="/dashboard" replace />} />
      </Routes>
    </Suspense>
  );
}
