import { useConvexAccessToken, WebAuthProvider } from "@code/auth/web";
import { env } from "@code/env/web";
import { Toaster } from "@code/ui/components/sonner";
import { FlueProvider } from "@flue/react";

import "./index.css";
import { createFlueClient } from "@flue/sdk";
import { useMemo } from "react";
import {
  isRouteErrorResponse,
  Links,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
} from "react-router";

import type { Route } from "./+types/root";
import { ThemeProvider } from "./components/theme-provider";
import { createFlueFetch } from "./lib/flue-transport";

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",
  },
];

const flueBaseUrl = new URL(env.VITE_FLUE_URL);
const flueFetch = createFlueFetch({ baseUrl: flueBaseUrl });

const AuthenticatedFlueProvider = ({
  children,
}: {
  children: React.ReactNode;
}) => {
  const resolveAccessToken = useConvexAccessToken();
  const client = useMemo(
    () =>
      createFlueClient({
        baseUrl: flueBaseUrl.toString(),
        fetch: flueFetch,
        headers: async () => {
          const accessToken = await resolveAccessToken();
          const headers: Record<string, string> = {};
          if (accessToken) {
            headers.authorization = `Bearer ${accessToken}`;
          }
          return headers;
        },
      }),
    [resolveAccessToken]
  );

  return <FlueProvider client={client}>{children}</FlueProvider>;
};
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" />
      <Meta />
      <Links />
    </head>
    <body className="bg-[#0e0e0d]">
      {children}
      <ScrollRestoration />
      <Scripts />
    </body>
  </html>
);

const App = () => (
  <WebAuthProvider>
    <AuthenticatedFlueProvider>
      <ThemeProvider
        attribute="class"
        defaultTheme="dark"
        forcedTheme="dark"
        disableTransitionOnChange
        storageKey="vite-ui-theme"
      >
        <Outlet />
        <Toaster richColors />
      </ThemeProvider>
    </AuthenticatedFlueProvider>
  </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>
  );
};
