import type { NextConfig } from "next";
import createMDX from "@next/mdx";

const nextConfig: NextConfig = {
  // Let .mdx files act as pages (the /docs section).
  pageExtensions: ["js", "jsx", "ts", "tsx", "mdx"],
  // Cache Components: routes are dynamic by default; opt into static with "use cache".
  cacheComponents: true,
  // Only the docs and blog routes render MDX, so trace the .mdx sources just for
  // those (keys are Next's normalized route paths — route groups like
  // `(marketing)` aren't part of the URL, so blog is `/[lang]/blog/**`). A broad
  // `/**/*` would needlessly bundle every .mdx into every serverless function.
  outputFileTracingIncludes: {
    "/[lang]/docs/**": ["./app/**/*.mdx"],
    "/[lang]/blog/**": ["./app/**/*.mdx"],
  },
  // Security headers on every response. The CSP is deliberately permissive
  // enough not to break the site: Next inlines CSS (experimental.inlineCss) and
  // hydrates with inline scripts, OpenPanel's recorder is served first-party
  // (`/op1.js`) but its events POST to a self-hosted instance, and GA4 loads via
  // googletagmanager.com. `'unsafe-inline'`/`'unsafe-eval'` stay because Next's
  // inline styles and hydration rely on them.
  async headers() {
    // OpenPanel events POST to a self-hosted instance, whose origin is set via
    // NEXT_PUBLIC_OP_API_URL (e.g. https://analytics.example.com/api). Derive the
    // origin from that same public env var and allow it in `connect-src`, so the
    // CSP follows the configured instance instead of hardcoding a domain (and
    // doesn't silently block tracking like `*.openpanel.dev`-only did).
    let opOrigin = "";
    const opApiUrl = process.env.NEXT_PUBLIC_OP_API_URL;
    if (opApiUrl) {
      try {
        opOrigin = new URL(opApiUrl).origin;
      } catch {
        opOrigin = "";
      }
    }
    const connectSrc = [
      "'self'",
      "https://*.openpanel.dev",
      "https://*.google-analytics.com",
      "https://www.googletagmanager.com",
      opOrigin,
    ]
      .filter(Boolean)
      .join(" ");

    const csp = [
      "default-src 'self'",
      "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.openpanel.dev https://www.googletagmanager.com https://*.google-analytics.com",
      "style-src 'self' 'unsafe-inline'",
      "img-src 'self' data: blob: https:",
      "font-src 'self' data:",
      `connect-src ${connectSrc}`,
      "frame-ancestors 'self'",
      "base-uri 'self'",
      "form-action 'self'",
    ].join("; ");

    return [
      {
        source: "/(.*)",
        headers: [
          { key: "X-Content-Type-Options", value: "nosniff" },
          { key: "X-Frame-Options", value: "SAMEORIGIN" },
          {
            key: "Referrer-Policy",
            value: "strict-origin-when-cross-origin",
          },
          { key: "X-DNS-Prefetch-Control", value: "on" },
          {
            key: "Strict-Transport-Security",
            value: "max-age=63072000; includeSubDomains; preload",
          },
          {
            key: "Permissions-Policy",
            value: "camera=(), microphone=(), geolocation=()",
          },
          { key: "Content-Security-Policy", value: csp },
        ],
      },
    ];
  },
  experimental: {
    // Tree-shake the motion barrel so we only ship the animation primitives we
    // use (@tabler/icons-react and lucide-react are optimized by default).
    optimizePackageImports: ["motion"],
    // Inline the compiled Tailwind CSS into <head> as a <style> tag instead of
    // a render-blocking <link>. Our atomic CSS bundle is small (~15 KB), so the
    // styles arrive with the HTML and the browser renders without a round-trip —
    // a win for first-time-visitor FCP/LCP on this marketing site.
    inlineCss: true,
  },
};

// Turbopack only accepts plugins referenced by string name with serializable
// options (functions can't cross into the Rust bundler) — per the Next.js MDX guide.
const withMDX = createMDX({
  options: {
    remarkPlugins: ["remark-gfm"],
    rehypePlugins: [
      "rehype-slug",
      [
        "rehype-pretty-code",
        {
          // Single dark theme — code panels are always dark (Protocol style);
          // the <Pre> component paints the dark background.
          theme: "github-dark-dimmed",
          keepBackground: false,
        },
      ],
    ],
  },
});

export default withMDX(nextConfig);
