import type { Metadata, Viewport } from "next";
import {
  Atkinson_Hyperlegible,
  EB_Garamond,
  Geist,
  Geist_Mono,
  Inter,
  JetBrains_Mono,
  Lora,
  Merriweather,
  Open_Sans,
  Playfair_Display,
  Source_Serif_4,
  Space_Grotesk,
  Work_Sans,
} from "next/font/google";
import "./globals.css";
import type { Settings } from "@/db/schema";
import { FEED_PATH, resolveSiteUrl } from "@/lib/seo";
import { DEFAULT_SETTINGS, getSettings } from "@/lib/services/settings";
import { THEME_META } from "@/lib/themes";

// The entire site is driven by database content that admins change at any
// time, so every route renders per request (no build-time DB dependency).
// Incremental caching/revalidation is a documented future optimization.
export const dynamic = "force-dynamic";

// All selectable body fonts are self-hosted by next/font at build time.
// Only Geist (the default) is preloaded; the others declare @font-face
// rules and are fetched by the browser solely when the admin-selected
// data-font attribute makes one of them the active --font-body.
const geistSans = Geist({
  variable: "--font-geist-sans",
  subsets: ["latin"],
});

const geistMono = Geist_Mono({
  variable: "--font-geist-mono",
  subsets: ["latin"],
});

const inter = Inter({
  variable: "--font-inter",
  subsets: ["latin"],
  preload: false,
});

const lora = Lora({
  variable: "--font-lora",
  subsets: ["latin"],
  style: ["normal", "italic"],
  preload: false,
});

const merriweather = Merriweather({
  variable: "--font-merriweather",
  subsets: ["latin"],
  weight: ["300", "400", "700"],
  style: ["normal", "italic"],
  preload: false,
});

const jetbrainsMono = JetBrains_Mono({
  variable: "--font-jetbrains-mono",
  subsets: ["latin"],
  style: ["normal", "italic"],
  preload: false,
});

const sourceSerif = Source_Serif_4({
  variable: "--font-source-serif",
  subsets: ["latin"],
  style: ["normal", "italic"],
  preload: false,
});

const ebGaramond = EB_Garamond({
  variable: "--font-eb-garamond",
  subsets: ["latin"],
  style: ["normal", "italic"],
  preload: false,
});

const playfair = Playfair_Display({
  variable: "--font-playfair",
  subsets: ["latin"],
  style: ["normal", "italic"],
  preload: false,
});

const openSans = Open_Sans({
  variable: "--font-open-sans",
  subsets: ["latin"],
  style: ["normal", "italic"],
  preload: false,
});

const workSans = Work_Sans({
  variable: "--font-work-sans",
  subsets: ["latin"],
  style: ["normal", "italic"],
  preload: false,
});

const atkinson = Atkinson_Hyperlegible({
  variable: "--font-atkinson",
  subsets: ["latin"],
  weight: ["400", "700"],
  style: ["normal", "italic"],
  preload: false,
});

const spaceGrotesk = Space_Grotesk({
  variable: "--font-space-grotesk",
  subsets: ["latin"],
  preload: false,
});

const fontVariables = [
  geistSans.variable,
  geistMono.variable,
  inter.variable,
  lora.variable,
  merriweather.variable,
  jetbrainsMono.variable,
  sourceSerif.variable,
  ebGaramond.variable,
  playfair.variable,
  openSans.variable,
  workSans.variable,
  atkinson.variable,
  spaceGrotesk.variable,
].join(" ");

/** The chrome must render even when the DB is down; fall back to defaults. */
async function settingsOrDefaults(): Promise<Settings> {
  try {
    return await getSettings();
  } catch {
    return DEFAULT_SETTINGS;
  }
}

export async function generateMetadata(): Promise<Metadata> {
  const settings = await settingsOrDefaults();
  return {
    // Resolves every relative canonical/OG URL below to the public origin.
    metadataBase: new URL(resolveSiteUrl(settings)),
    title: { default: settings.siteTitle, template: `%s · ${settings.siteTitle}` },
    description: settings.headerText || undefined,
    alternates: {
      types: { "application/rss+xml": [{ url: FEED_PATH, title: settings.siteTitle }] },
    },
    openGraph: {
      siteName: settings.siteTitle,
      type: "website",
      locale: "en",
    },
  };
}

export async function generateViewport(): Promise<Viewport> {
  const { theme } = await settingsOrDefaults();
  return { themeColor: THEME_META[theme].bg };
}

export default async function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  const { theme, font } = await settingsOrDefaults();
  return (
    <html
      lang="en"
      data-theme={theme}
      data-font={font}
      className={`${fontVariables} h-full antialiased`}
    >
      <body className="flex min-h-dvh flex-col font-sans">
        <a
          href="#main"
          className="sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-4 focus:z-[100] focus:rounded-md focus:bg-link focus:px-4 focus:py-2 focus:text-ink-inverse"
        >
          Skip to content
        </a>
        {children}
      </body>
    </html>
  );
}
