import {
   isRouteErrorResponse,
   Links,
   Meta,
   Outlet,
   Scripts,
   ScrollRestoration,
} from 'react-router';

import type { Route } from './+types/root';
import './app.css';
import Navbar from './components/Navbar';
import ToastProvider from './components/toast/ToastProvider';
import { getOptionalAuth } from './lib/auth.server';

export const links: Route.LinksFunction = () => [
   { rel: 'preconnect', href: 'https://fonts.googleapis.com' },
   {
      rel: 'preconnect',
      href: 'https://fonts.gstatic.com',
      crossOrigin: 'anonymous',
   },
   {
      rel: 'stylesheet',
      href: 'https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..900;1,9..40,100..900&family=Volkhov:ital,wght@0,400;0,700;1,400;1,700&display=swap',
   },
];

export const loader = async ({ request }: Route.LoaderArgs) => {
   const auth = await getOptionalAuth(request);
   return { auth };
};

export function Layout({ children }: { children: React.ReactNode }) {
   return (
      <html lang="en">
         <head>
            <meta charSet="utf-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1" />
            <Meta />
            <Links />
         </head>
         <body>
            {children}
            <ScrollRestoration />
            <Scripts />
         </body>
      </html>
   );
}

export default function App({ loaderData }: Route.ComponentProps) {
   const { auth } = loaderData;
   return (
      <>
         <Navbar auth={auth} />
         <ToastProvider />
         <Outlet />
      </>
   );
}

export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
   let message = 'Oops!';
   let details = 'An unexpected error occurred.';
   let stack: string | undefined;

   if (isRouteErrorResponse(error)) {
      message = error.status === 404 ? '404' : 'Error';
      details =
         error.status === 404
            ? 'The requested page could not be found.'
            : error.statusText || details;
   } else if (import.meta.env.DEV && error && error instanceof Error) {
      details = error.message;
      stack = error.stack;
   }

   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>
   );
}
