import type { ReactNode } from 'react';
import type { Metadata, Viewport } from 'next';
import localFont from 'next/font/local';
import { Space_Grotesk } from 'next/font/google';
import { setRequestLocale, getMessages, getTranslations } from 'next-intl/server';
import { NextIntlClientProvider } from 'next-intl';
import { getThemeMode } from '@/lib/cookies/server';
import { getServerAuthState } from '@/lib/auth/server';
import { AuthProvider } from '@/context/auth';
import { ThemeProvider, getDirection } from '@/theme';
import { BRAND } from '@/theme/colors';
import { NotistackProvider } from '@/lib/toast';
import { QueryProvider } from '@/lib/query/QueryProvider';
import { routing } from '@/i18n/routing';
import '../globals.css';
import '@/theme/tokens.css';

/*
 * This is the application's ROOT layout — it renders <html> and <body>.
 *
 * Why <html> lives here and NOT in a layout above the [locale] segment:
 * `lang` and `dir` must track the active locale, and the only layout that
 * re-renders when the locale changes is the one keyed on the [locale] param.
 * A layout placed above [locale] is shared between /fa and /en, so it is
 * statically cached with the defaultLocale and never re-renders on a locale
 * switch — leaving `dir`/`lang` frozen on the default ('fa'/'rtl'). Sourcing
 * the locale from URL params here means no header reads, no caching surprises.
 *
 * setRequestLocale(locale) is called first so that any server component
 * deeper in the tree that calls getLocale() / getTranslations() gets the
 * right locale from React.cache instead of falling through to the header
 * fallback. getMessages({ locale }) passes the locale explicitly so the
 * config callback in src/i18n/request.ts receives it via requestLocale
 * directly (Promise.resolve(locale)) rather than reading it from the cache.
 */

// FA brand font — Mikhak, a free Persian typeface.
// preload: false + conditional className (below) ensure the woff2 files are
// only fetched on Persian routes, never on /en.
const mikhak = localFont({
  src: [
    { path: '../fonts/Mikhak-Regular.woff2', weight: '400', style: 'normal' },
    { path: '../fonts/Mikhak-Medium.woff2',  weight: '500', style: 'normal' },
    { path: '../fonts/Mikhak-Bold.woff2',    weight: '700', style: 'normal' },
  ],
  display: 'swap',
  variable: '--font-mikhak',
  preload: false,
});

// EN brand font — Space Grotesk. Self-hosted by next/font/google at build
// time (no runtime Google Fonts request). Same discipline as Mikhak:
// preload: false + conditional className below so it is only fetched on `en`.
const spaceGrotesk = Space_Grotesk({
  subsets: ['latin'],
  weight: ['400', '500', '700'],
  display: 'swap',
  variable: '--font-space-grotesk',
  preload: false,
});

export const viewport: Viewport = {
  themeColor: [
    { media: '(prefers-color-scheme: light)', color: BRAND.teal },
    { media: '(prefers-color-scheme: dark)', color: BRAND.tealDeep },
  ],
};

export async function generateMetadata({
  params,
}: {
  params: Promise<{ locale: string }>;
}): Promise<Metadata> {
  const { locale } = await params;

  const safeLocale = routing.locales.includes(locale as (typeof routing.locales)[number])
    ? locale
    : routing.defaultLocale;

  const t = await getTranslations({ locale: safeLocale, namespace: 'common' });

  return {
    title: {
      template: safeLocale === 'fa' ? '%s | بالین‌یار' : '%s | Balinyaar',
      default: safeLocale === 'fa' ? 'بالین‌یار' : 'Balinyaar',
    },
    description: t('brand_tagline'),
    manifest: '/site.webmanifest',
  };
}

export default async function LocaleLayout({
  children,
  params,
}: {
  children: ReactNode;
  params: Promise<{ locale: string }>;
}) {
  const { locale } = await params;

  const safeLocale = routing.locales.includes(locale as (typeof routing.locales)[number])
    ? locale
    : routing.defaultLocale;

  setRequestLocale(safeLocale);

  const messages = await getMessages({ locale: safeLocale });
  const { colorScheme, defaultMode } = await getThemeMode();
  const authState = await getServerAuthState();
  const dir = getDirection(safeLocale);

  // Each locale's brand font variable is attached only on its own routes —
  // Mikhak never ships to /en, Space Grotesk never ships to /fa.
  const fontClassName = safeLocale === 'fa' ? mikhak.variable : spaceGrotesk.variable;

  return (
    <html
      lang={safeLocale}
      dir={dir}
      className={fontClassName}
      data-mui-color-scheme={colorScheme}
    >
      <body>
        <NextIntlClientProvider locale={safeLocale} messages={messages}>
          <AuthProvider initialState={authState}>
            <ThemeProvider dir={dir} defaultMode={defaultMode}>
              <QueryProvider>
                <NotistackProvider>
                  {children}
                </NotistackProvider>
              </QueryProvider>
            </ThemeProvider>
          </AuthProvider>
        </NextIntlClientProvider>
      </body>
    </html>
  );
}

export function generateStaticParams() {
  return routing.locales.map((locale) => ({ locale }));
}
