import { WebAuthProvider } from "@code/auth/web";
import { Toaster } from "@code/ui/components/sonner";

import "./index.css";
import { LoaderCircle } from "lucide-react";
import {
  isRouteErrorResponse,
  Links,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
  useNavigation,
} from "react-router";

import type { Route } from "./+types/root";
import { ThemeProvider } from "./components/theme-provider";
import { loadAuthToken } from "./lib/auth.server";

export const loader = ({ request }: Route.LoaderArgs) => loadAuthToken(request);

export const links: Route.LinksFunction = () => [
  { href: "https://fonts.googleapis.com", rel: "preconnect" },
  {
    crossOrigin: "anonymous",
    href: "https://fonts.gstatic.com",
    rel: "preconnect",
  },
  {
    href: "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap",
    rel: "stylesheet",
  },
];

export const Layout = ({ children }: { children: React.ReactNode }) => (
  <html lang="en">
    <head>
      <meta charSet="utf-8" />
      <meta
        name="viewport"
        content="width=device-width, initial-scale=1, interactive-widget=resizes-content"
      />
      <Meta />
      <Links />
    </head>
    <body className="bg-[#0e0e0d]">
      {children}
      <ScrollRestoration />
      <Scripts />
    </body>
  </html>
);

const RouteProgress = () => {
  const navigation = useNavigation();
  if (!navigation.location) {
    return null;
  }
  return (
    <output
      aria-label="Loading page"
      className="fixed inset-x-0 top-0 z-50 h-0.5 overflow-hidden bg-[#d7d3c7]"
    >
      <div className="route-progress-bar h-full w-1/3 bg-[#7f9130]" />
    </output>
  );
};

export const HydrateFallback = () => (
  <main className="grid min-h-svh place-items-center bg-[#f2f0e7] text-[#69675f]">
    <div className="flex items-center gap-2 text-sm">
      <LoaderCircle className="size-4 animate-spin" /> Loading Zopu…
    </div>
  </main>
);

const App = ({ loaderData }: Route.ComponentProps) => (
  <WebAuthProvider initialToken={loaderData.token}>
    <ThemeProvider
      attribute="class"
      defaultTheme="dark"
      forcedTheme="dark"
      disableTransitionOnChange
      storageKey="vite-ui-theme"
    >
      <RouteProgress />
      <Outlet />
      <Toaster richColors />
    </ThemeProvider>
  </WebAuthProvider>
);

export default App;

export const ErrorBoundary = ({ error }: Route.ErrorBoundaryProps) => {
  let message = "Oops!";
  let details = "An unexpected error occurred.";
  let stack: string | undefined;
  if (isRouteErrorResponse(error)) {
    const { status, statusText } = error;
    message = status === 404 ? "404" : "Error";
    details =
      status === 404
        ? "The requested page could not be found."
        : statusText || details;
  } else if (import.meta.env.DEV && error && error instanceof Error) {
    ({ message: details, stack } = error);
  }
  return (
    <main className="pt-16 p-4 container mx-auto">
      <h1>{message}</h1>
      <p>{details}</p>
      {stack && (
        <pre className="w-full p-4 overflow-x-auto">
          <code>{stack}</code>
        </pre>
      )}
    </main>
  );
};
