import { lazy, Suspense } from "react";
import { BrowserRouter, Navigate, Route, Routes } from "react-router";

import { RestrictedGuest } from "./pages/RestrictedGuest.tsx";
import { RestrictedLoggedIn } from "./pages/RestrictedLoggedIn.tsx";
import { useAuth } from "./hooks/useAuth.ts";
import { useDefaultFeedTab } from "./hooks/useDefaultFeedTab.ts";

import { AuthProvider } from "./contexts/AuthProvider.tsx";
import { PlayerProvider } from "./contexts/PlayerProvider.tsx";
import { WSProvider } from "./contexts/WSProvider.tsx";
import { FollowProvider } from "./contexts/FollowProvider.tsx";
import { ThemeProvider } from "./contexts/ThemeProvider.tsx";
import { GlobalPlayer } from "./components/GlobalPlayer.tsx";
import { DumpFab } from "./components/DumpFab.tsx";

import "./App.css";

const Index = lazy(() =>
  import("./pages/Index.tsx").then((m) => ({ default: m.Index }))
);
const Dump = lazy(() =>
  import("./pages/Dump.tsx").then((m) => ({ default: m.Dump }))
);
const DumpEdit = lazy(() =>
  import("./pages/DumpEdit.tsx").then((m) => ({ default: m.DumpEdit }))
);
const UserLogin = lazy(() =>
  import("./pages/UserLogin.tsx").then((m) => ({ default: m.UserLogin }))
);
const UserPublicProfile = lazy(() =>
  import("./pages/UserPublicProfile.tsx").then((m) => ({
    default: m.UserPublicProfile,
  }))
);
const UserRegister = lazy(() =>
  import("./pages/UserRegister.tsx").then((m) => ({ default: m.UserRegister }))
);
const UserDumps = lazy(() =>
  import("./pages/UserDumps.tsx").then((m) => ({ default: m.UserDumps }))
);
const UserUpvoted = lazy(() =>
  import("./pages/UserUpvoted.tsx").then((m) => ({ default: m.UserUpvoted }))
);
const UserPlaylists = lazy(() =>
  import("./pages/UserPlaylists.tsx").then((m) => ({
    default: m.UserPlaylists,
  }))
);
const PlaylistDetail = lazy(() =>
  import("./pages/PlaylistDetail.tsx").then((m) => ({
    default: m.PlaylistDetail,
  }))
);
const Notifications = lazy(() =>
  import("./pages/Notifications.tsx").then((m) => ({
    default: m.Notifications,
  }))
);
const Search = lazy(() =>
  import("./pages/Search.tsx").then((m) => ({ default: m.Search }))
);
const ResetPassword = lazy(() =>
  import("./pages/ResetPassword.tsx").then((m) => ({
    default: m.ResetPassword,
  }))
);
const NotFound = lazy(() =>
  import("./pages/NotFound.tsx").then((m) => ({ default: m.NotFound }))
);

function IndexRedirect() {
  const { user } = useAuth();
  const [preferredTab] = useDefaultFeedTab();
  // "followed" requires a session, so fall back to "hot" for guests.
  const tab = preferredTab === "followed" && !user ? "hot" : preferredTab;
  return <Navigate to={`/~/${tab}`} replace />;
}

function AppRoutes() {
  return (
    <>
      <Suspense>
        <Routes>
          <Route path="/" element={<IndexRedirect />} />
          <Route path="/~/:feedTab" element={<Index />} />
          <Route path="/dumps/:selectedDump" element={<Dump />} />
          <Route
            path="/dumps/:selectedDump/edit"
            element={
              <RestrictedLoggedIn>
                <DumpEdit />
              </RestrictedLoggedIn>
            }
          />
          <Route
            path="/register"
            element={
              <RestrictedGuest>
                <UserRegister />
              </RestrictedGuest>
            }
          />
          <Route
            path="/login"
            element={
              <RestrictedGuest>
                <UserLogin />
              </RestrictedGuest>
            }
          />
          <Route path="/users/:username" element={<UserPublicProfile />} />
          <Route
            path="/users/:username/~/:profileTab"
            element={<UserPublicProfile />}
          />
          <Route path="/users/:username/dumps" element={<UserDumps />} />
          <Route path="/users/:username/upvoted" element={<UserUpvoted />} />
          <Route
            path="/users/:username/playlists"
            element={<UserPlaylists />}
          />
          <Route path="/playlists/:playlistId" element={<PlaylistDetail />} />
          <Route path="/search" element={<Search />} />
          <Route path="/search/~/:searchTab" element={<Search />} />
          <Route path="/reset-password" element={<ResetPassword />} />
          <Route
            path="/notifications"
            element={
              <RestrictedLoggedIn>
                <Notifications />
              </RestrictedLoggedIn>
            }
          />
          <Route path="*" element={<NotFound />} />
        </Routes>
      </Suspense>
      <DumpFab />
    </>
  );
}

function App() {
  return (
    <ThemeProvider>
      <AuthProvider>
        <PlayerProvider>
          <WSProvider>
            <FollowProvider>
              <BrowserRouter>
                <AppRoutes />
              </BrowserRouter>
            </FollowProvider>
          </WSProvider>
          <GlobalPlayer />
        </PlayerProvider>
      </AuthProvider>
    </ThemeProvider>
  );
}

export default App;
