import {
  HeadContent,
  Navigate,
  Outlet,
  Scripts,
  createRootRouteWithContext,
  isRedirect,
} from "@tanstack/react-router";
import * as React from "react";
import { DefaultCatchBoundary } from "@/components/DefaultCatchBoundary";
import { type QueryClient } from "@tanstack/react-query";
import { ensureSuperTokensFrontend } from "@/lib/supertokens/client";
import { AuthContextType } from "@/contexts/auth-context";
import Providers from "@/features/core/components/providers";
import { SessionMonitor } from "@/components/session-monitor";
import { IOSInstallPrompt } from "@/components/ios-install-prompt";
import { ColorSchemeScript, mantineHtmlProps } from "@mantine/core";
import { HeaderConfig } from "@/features/core/types/header-config";
import { playerQueries } from "@/features/players/queries";
import { ensureServerQueryData } from "@/lib/tanstack-query/utils/ensure";
import { DEFAULT_LOCALE, ensureMessages, resolveLocale } from "@/lib/i18n";
import { getRootMeta } from "@/lib/i18n/meta";
import FullScreenLoader from "@/components/full-screen-loader";
import { CHROME_COLORS } from "@/lib/mantine/theme-colors";
import mantineCssUrl from '@mantine/core/styles.css?url'
import mantineDatesCssUrl from '@mantine/dates/styles.css?url'
import mantineCarouselCssUrl from '@mantine/carousel/styles.css?url'
import mantineTiptapCssUrl from '@mantine/tiptap/styles.css?url'

export const Route = createRootRouteWithContext<{
  queryClient: QueryClient;
  auth: AuthContextType;
  header: HeaderConfig;
  refresh: string[];
  withPadding: boolean;
  fullWidth: boolean;
}>()({
  head: () => {
    // Meta stays DEFAULT_LOCALE: crawlers/unfurlers have no session, and
    // reading match.context here creates circular route-type inference that
    // breaks beforeLoad typing in child routes.
    const rootMeta = getRootMeta(DEFAULT_LOCALE);

    return {
      title: "FLXN IX",
      meta: [
        {
          charSet: "utf-8",
        },
        {
          name: "viewport",
          content:
            "width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, interactive-widget=resizes-content, viewport-fit=cover",
        },
        { name: 'description', content: rootMeta.description },
        { name: 'keywords', content: 'FLXN, beer pong, tournament, sports, statistics, pong' },
        { property: 'og:title', content: 'FLXN' },
        { property: 'og:description', content: rootMeta.description },
        { property: 'og:url', content: 'https://flexxon.app' },
        { property: 'og:type', content: 'website' },
        { property: 'og:site_name', content: 'FLXN' },
        { property: 'og:image', content: 'https://flexxon.app/favicon.png' },
        { property: 'og:image:width', content: '512' },
        { property: 'og:image:height', content: '512' },
        { property: 'og:image:alt', content: rootMeta.ogImageAlt },
        { property: 'og:locale', content: rootMeta.ogLocale },
        { name: 'twitter:card', content: 'summary' },
        { name: 'twitter:title', content: 'FLXN' },
        { name: 'twitter:description', content: rootMeta.description },
        { name: 'twitter:image', content: 'https://flexxon.app/favicon.png' },
        { name: 'mobile-web-app-capable', content: 'yes' },
        { name: 'apple-mobile-web-app-capable', content: 'yes' },
        { name: 'apple-mobile-web-app-status-bar-style', content: 'default' },
        { name: 'apple-mobile-web-app-title', content: 'FLXN' },
      ],
      links: [
        {
          rel: "apple-touch-icon",
          sizes: "180x180",
          href: "/apple-touch-icon.png",
        },
        {
          rel: "icon",
          type: "image/png",
          sizes: "32x32",
          href: "/favicon-32x32.png",
        },
        {
          rel: "icon",
          type: "image/png",
          sizes: "16x16",
          href: "/favicon-16x16.png",
        },
        { rel: "manifest", href: "/site.webmanifest" },
        { rel: "icon", href: "/favicon.ico" },
        { rel: 'stylesheet', href: mantineCssUrl },
        { rel: 'stylesheet', href: mantineCarouselCssUrl },
        { rel: 'stylesheet', href: mantineDatesCssUrl },
        { rel: 'stylesheet', href: mantineTiptapCssUrl },
        { 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=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=League+Spartan:wght@100..900&display=swap",
        }
      ],
    };
  },
  errorComponent: (props) => {
    return (
      <RootDocument>
        <Providers>
          <DefaultCatchBoundary {...props} />
        </Providers>
      </RootDocument>
    );
  },
  component: RootComponent,
  notFoundComponent: () => <Navigate to="/" />,
  beforeLoad: async ({ context, location }) => {
    const publicRoutes = ['/login', '/logout', '/refresh-session'];
    if (publicRoutes.some(route => location.pathname.startsWith(route))) {
      return {};
    }

    try {
      const auth = await ensureServerQueryData(
        context.queryClient,
        playerQueries.auth()
      );
      await ensureMessages(resolveLocale(auth?.metadata?.locale));
      return { auth };
    } catch (error: any) {
      if (isRedirect(error) || error instanceof Response) throw error;

      if (typeof window !== 'undefined') {
        const { doesSessionExist, attemptRefreshingSession } = await import('supertokens-web-js/recipe/session');

        const sessionExists = await doesSessionExist();
        if (sessionExists) {
          try {
            await attemptRefreshingSession();
            const auth = await ensureServerQueryData(
              context.queryClient,
              playerQueries.auth()
            );
            await ensureMessages(resolveLocale(auth?.metadata?.locale));
            return { auth };
          } catch {
            return {};
          }
        }
      }
      return {};
    }
  },
  pendingComponent: () => <Providers><FullScreenLoader /></Providers>,
});

function RootComponent() {
  React.useEffect(() => {
    ensureSuperTokensFrontend();
    if (import.meta.env.PROD && 'serviceWorker' in navigator) {
      navigator.serviceWorker.register('/sw.js').catch(() => {});
    }
  }, []);

  return (
    <RootDocument>
      <Providers>
        <SessionMonitor />
        <IOSInstallPrompt />
        <Outlet />
      </Providers>
    </RootDocument>
  );
}

// todo: analytics -> process.env data-website-id
function RootDocument({ children }: { children: React.ReactNode }) {
  return (
    <html
      {...mantineHtmlProps}
      style={{
        overflowX: "hidden",
        height: "100%",
        width: "100%",
      }}
    >
      <head>
        <HeadContent />
        <meta
          name="theme-color"
          media="(prefers-color-scheme: light)"
          content={CHROME_COLORS.light.base}
        />
        <meta
          name="theme-color"
          media="(prefers-color-scheme: dark)"
          content={CHROME_COLORS.dark.base}
        />
        <ColorSchemeScript />
        <link rel="stylesheet" href="/styles.css" />
      </head>
      <body
        style={{
          overflowX: "hidden",
          height: "100%",
          width: "100%",
          margin: 0,
          padding: 0,
        }}
      >
        <div className="app">{children}</div>
        <Scripts />
      </body>
    </html>
  );
}
