import type { Metadata } from "next";
import localFont from "next/font/local";
import { PublicEnvScript } from "next-runtime-env";
import { AppShell } from "./_parts/app-shell";
import { MswInit } from "./_parts/msw-init";
import { PostHogProviderWrapper } from "./_parts/posthog-provider";
import { ArchestraQueryClientProvider } from "./_parts/query-client-provider";
import { ThemeProvider } from "./_parts/theme-provider";
import "./globals.css";
import { DEFAULT_APP_DESCRIPTION } from "@shared";
import { DynamicHead } from "@/components/dynamic-head";
import { OrgThemeLoader } from "@/components/org-theme-loader";
import { ChatProvider } from "@/lib/chat/global-chat.context";
import { WebsocketInitializer } from "./_parts/websocket-initializer";
import { WithAuthCheck } from "./_parts/with-auth-check";
import { WithPagePermissions } from "./_parts/with-page-permissions";
import { AuthProvider } from "./auth/auth-provider";

// Register theme fonts for white-labeling without preloading every file.
// The active theme decides which CSS variable is used after appearance settings
// load, so eager preload would fetch every optional font on every page.
const latoFont = localFont({
  src: [
    { path: "../fonts/Lato-Light.woff2", weight: "300" },
    { path: "../fonts/Lato-Regular.woff2", weight: "400" },
    { path: "../fonts/Lato-Bold.woff2", weight: "700" },
    { path: "../fonts/Lato-Black.woff2", weight: "900" },
  ],
  variable: "--font-lato",
  display: "swap",
  preload: false,
});

const interFont = localFont({
  src: "../fonts/Inter-Variable.woff2",
  variable: "--font-inter",
  weight: "100 900",
  display: "swap",
  preload: false,
});

const openSansFont = localFont({
  src: "../fonts/OpenSans-Variable.woff2",
  variable: "--font-open-sans",
  weight: "300 800",
  display: "swap",
  preload: false,
});

const robotoFont = localFont({
  src: "../fonts/Roboto-Variable.woff2",
  variable: "--font-roboto",
  weight: "100 900",
  display: "swap",
  preload: false,
});

const sourceSansFont = localFont({
  src: "../fonts/SourceSans3-Variable.woff2",
  variable: "--font-source-sans",
  weight: "200 900",
  display: "swap",
  preload: false,
});

const jetbrainsMonoFont = localFont({
  src: "../fonts/JetBrainsMono-Variable.woff2",
  variable: "--font-jetbrains-mono",
  weight: "100 800",
  display: "swap",
  preload: false,
});

const dmSansFont = localFont({
  src: "../fonts/DMSans-Variable.woff2",
  variable: "--font-dm-sans",
  weight: "100 1000",
  display: "swap",
  preload: false,
});

const poppinsFont = localFont({
  src: [
    { path: "../fonts/Poppins-Light.woff2", weight: "300" },
    { path: "../fonts/Poppins-Regular.woff2", weight: "400" },
    { path: "../fonts/Poppins-Medium.woff2", weight: "500" },
    { path: "../fonts/Poppins-SemiBold.woff2", weight: "600" },
    { path: "../fonts/Poppins-Bold.woff2", weight: "700" },
  ],
  variable: "--font-poppins",
  display: "swap",
  preload: false,
});

const oxaniumFont = localFont({
  src: "../fonts/Oxanium-Variable.woff2",
  variable: "--font-oxanium",
  weight: "200 800",
  display: "swap",
  preload: false,
});

const montserratFont = localFont({
  src: "../fonts/Montserrat-Variable.woff2",
  variable: "--font-montserrat",
  weight: "100 900",
  display: "swap",
  preload: false,
});

const sourceCodeProFont = localFont({
  src: "../fonts/SourceCodePro-Variable.woff2",
  variable: "--font-source-code-pro",
  weight: "200 900",
  display: "swap",
  preload: false,
});

const merriweatherFont = localFont({
  src: "../fonts/Merriweather-Variable.woff2",
  variable: "--font-merriweather",
  weight: "300 900",
  display: "swap",
  preload: false,
});

const quicksandFont = localFont({
  src: "../fonts/Quicksand-Variable.woff2",
  variable: "--font-quicksand",
  weight: "300 700",
  display: "swap",
  preload: false,
});

const outfitFont = localFont({
  src: "../fonts/Outfit-Variable.woff2",
  variable: "--font-outfit",
  weight: "100 900",
  display: "swap",
  preload: false,
});

const plusJakartaSansFont = localFont({
  src: "../fonts/PlusJakartaSans-Variable.woff2",
  variable: "--font-plus-jakarta-sans",
  weight: "200 800",
  display: "swap",
  preload: false,
});

const libreBaskervilleFont = localFont({
  src: "../fonts/LibreBaskerville-Variable.woff2",
  variable: "--font-libre-baskerville",
  weight: "400 700",
  display: "swap",
  preload: false,
});

export const metadata: Metadata = {
  description: DEFAULT_APP_DESCRIPTION,
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html
      lang="en"
      suppressHydrationWarning
      className={`${latoFont.variable} ${interFont.variable} ${openSansFont.variable} ${robotoFont.variable} ${sourceSansFont.variable} ${jetbrainsMonoFont.variable} ${dmSansFont.variable} ${poppinsFont.variable} ${oxaniumFont.variable} ${montserratFont.variable} ${sourceCodeProFont.variable} ${merriweatherFont.variable} ${quicksandFont.variable} ${outfitFont.variable} ${plusJakartaSansFont.variable} ${libreBaskervilleFont.variable}`}
    >
      <head>
        <PublicEnvScript />
        <link rel="icon" href="/favicon.ico" />
      </head>
      <body className="font-sans antialiased">
        <MswInit>
          <ArchestraQueryClientProvider>
            <AuthProvider>
              <ChatProvider>
                <ThemeProvider
                  attribute="class"
                  defaultTheme="light"
                  enableSystem
                  disableTransitionOnChange
                >
                  <PostHogProviderWrapper>
                    <OrgThemeLoader />
                    <DynamicHead />
                    <WithAuthCheck>
                      <WebsocketInitializer />
                      <AppShell>
                        <WithPagePermissions>{children}</WithPagePermissions>
                      </AppShell>
                    </WithAuthCheck>
                  </PostHogProviderWrapper>
                </ThemeProvider>
              </ChatProvider>
            </AuthProvider>
          </ArchestraQueryClientProvider>
        </MswInit>
      </body>
    </html>
  );
}
