import { Suspense, lazy } from 'react'
import { Route, Routes } from 'react-router-dom'

import { RouteAnnouncer } from '@/components/RouteAnnouncer'
import { PageSpinner } from '@/components/ui'
import { RequireAuth, RequireGuest } from '@/features/auth/RequireAuth'
import { HomePage } from '@/routes/marketplace/HomePage'

/*
 * Route-level code splitting.
 *
 * The landing page is imported eagerly because it is what an anonymous visitor
 * arrives on, and making them wait for a second round trip to see it would be
 * self-defeating. Everything else is deferred.
 *
 * Previously the whole application shipped in one chunk, so a visitor reading
 * the marketing page also downloaded the settings screens, the two-factor
 * enrolment flow and every auth form. That was tolerable at this size and would
 * not have stayed tolerable: search, portfolio management and the admin area are
 * the largest surfaces still to come, and the pattern needed fixing before they
 * were written rather than after.
 *
 * The chunks are grouped by when a person needs them, not one per file: the
 * settings screens are always reached together, so splitting them apart would
 * trade one request for three without changing what gets downloaded.
 */

const CategoriesPage = lazy(() =>
  import('@/routes/marketplace/CategoriesPage').then((m) => ({ default: m.CategoriesPage })),
)
const PricingPage = lazy(() =>
  import('@/routes/marketplace/PricingPage').then((m) => ({ default: m.PricingPage })),
)

/*
 * Search and the detail page. Each dynamic import is its own chunk, so these are
 * two -- around 11kB and 7kB, both well under the point where a second request
 * on navigation is worth avoiding by merging them.
 */
const DomainsPage = lazy(() =>
  import('@/routes/marketplace/DomainsPage').then((m) => ({ default: m.DomainsPage })),
)
const DomainDetailPage = lazy(() =>
  import('@/routes/marketplace/DomainDetailPage').then((m) => ({ default: m.DomainDetailPage })),
)
const PlaceholderPage = lazy(() =>
  import('@/routes/PlaceholderPage').then((m) => ({ default: m.PlaceholderPage })),
)
const NotFoundPage = lazy(() =>
  import('@/routes/NotFoundPage').then((m) => ({ default: m.NotFoundPage })),
)

const LoginPage = lazy(() =>
  import('@/routes/auth/LoginPage').then((m) => ({ default: m.LoginPage })),
)
const RegisterPage = lazy(() =>
  import('@/routes/auth/RegisterPage').then((m) => ({ default: m.RegisterPage })),
)
const ForgotPasswordPage = lazy(() =>
  import('@/routes/auth/ForgotPasswordPage').then((m) => ({ default: m.ForgotPasswordPage })),
)
const ResetPasswordPage = lazy(() =>
  import('@/routes/auth/ResetPasswordPage').then((m) => ({ default: m.ResetPasswordPage })),
)
const VerifyEmailPage = lazy(() =>
  import('@/routes/auth/VerifyEmailPage').then((m) => ({ default: m.VerifyEmailPage })),
)
const VerifyEmailPendingPage = lazy(() =>
  import('@/routes/auth/VerifyEmailPage').then((m) => ({ default: m.VerifyEmailPendingPage })),
)

const DashboardPage = lazy(() =>
  import('@/routes/DashboardPage').then((m) => ({ default: m.DashboardPage })),
)
const ProfileSettingsPage = lazy(() =>
  import('@/routes/account/ProfileSettingsPage').then((m) => ({ default: m.ProfileSettingsPage })),
)
const SecuritySettingsPage = lazy(() =>
  import('@/routes/account/SecuritySettingsPage').then((m) => ({
    default: m.SecuritySettingsPage,
  })),
)
const SellerSettingsPage = lazy(() =>
  import('@/routes/account/SellerSettingsPage').then((m) => ({ default: m.SellerSettingsPage })),
)

export function App() {
  return (
    /*
     * One boundary around the route table rather than per route. A route change
     * replaces the whole view, so a single fallback is what the user actually
     * perceives, and nesting boundaries would only add flicker.
     */
    <Suspense fallback={<PageSpinner label="Loading" />}>
      {/* Announces navigation and moves focus; renders nothing visible. */}
      <RouteAnnouncer />

      <Routes>
        {/* ------------------------------------------------------------ */}
        {/* Public. Browsing needs no account (spec section 30).          */}
        {/* ------------------------------------------------------------ */}
        <Route path="/" element={<HomePage />} />
        <Route path="/categories" element={<CategoriesPage />} />
        <Route path="/pricing" element={<PricingPage />} />

        {/*
          Search and the detail page. The URL shape (/domain/example.com) was
          fixed before anything indexed it and binds on the name rather than an
          id, so it stays stable as the marketplace grows.

          Offers and checkout are still later phases: the detail page renders its
          buy and offer actions as disabled and says why, rather than presenting
          controls that silently do nothing.
        */}
        <Route path="/domains" element={<DomainsPage />} />
        <Route path="/domain/:domain" element={<DomainDetailPage />} />
        <Route
          path="/seller/:handle"
          element={
            <PlaceholderPage
              phase="Phase 2"
              title="Public seller pages are being built"
              description="A seller's verification badges, rating and active listings will appear here."
            />
          }
        />
        <Route
          path="/sell"
          element={
            <PlaceholderPage
              phase="Phase 2"
              title="Domain listing is being built"
              description="Adding a domain, proving ownership by DNS record, and publishing a listing come next. You can set up your seller profile now."
            />
          }
        />

        {/* ------------------------------------------------------------ */}
        {/* Credentials                                                   */}
        {/* ------------------------------------------------------------ */}
        <Route
          path="/login"
          element={
            <RequireGuest>
              <LoginPage />
            </RequireGuest>
          }
        />
        <Route
          path="/register"
          element={
            <RequireGuest>
              <RegisterPage />
            </RequireGuest>
          }
        />
        <Route
          path="/forgot-password"
          element={
            <RequireGuest>
              <ForgotPasswordPage />
            </RequireGuest>
          }
        />
        <Route path="/reset-password" element={<ResetPasswordPage />} />

        {/* Reachable without a session: the link is clicked from an inbox. */}
        <Route path="/verify-email" element={<VerifyEmailPage />} />
        <Route path="/verify-email/pending" element={<VerifyEmailPendingPage />} />

        {/* ------------------------------------------------------------ */}
        {/* Members                                                       */}
        {/* ------------------------------------------------------------ */}
        <Route
          path="/dashboard"
          element={
            <RequireAuth>
              <DashboardPage />
            </RequireAuth>
          }
        />
        <Route
          path="/settings"
          element={
            <RequireAuth>
              <ProfileSettingsPage />
            </RequireAuth>
          }
        />
        <Route
          path="/settings/security"
          element={
            <RequireAuth>
              <SecuritySettingsPage />
            </RequireAuth>
          }
        />
        <Route
          path="/settings/seller"
          element={
            <RequireAuth>
              <SellerSettingsPage />
            </RequireAuth>
          }
        />

        <Route path="*" element={<NotFoundPage />} />
      </Routes>
    </Suspense>
  )
}
