import type { NextConfig } from "next";

import { laravelApiUrl } from "./src/lib/laravel-cms/environment";

const isProduction = process.env.NODE_ENV === "production";

// The website iframes nothing from here, but previews iframe the website.
const siteOrigin = (() => {
  try {
    return process.env.SITE_URL ? new URL(process.env.SITE_URL).origin : null;
  } catch {
    return null;
  }
})();

// The Laravel CMS (CMS_ENV or LARAVEL_API_URL) serves uploaded images. Read at build time for the rewrites below.
const cmsOrigin = (() => {
  try {
    return new URL(laravelApiUrl()).origin;
  } catch {
    return "https://secondphonenumber.worksqr.com";
  }
})();

/**
 * Content Security Policy for the admin. Next.js injects inline scripts for
 * hydration, so 'unsafe-inline' is needed without nonces; the rest is locked
 * to this origin. Images may come from any https host (external article
 * images, S3/R2 buckets).
 */
const contentSecurityPolicy = [
  "default-src 'self'",
  `script-src 'self' 'unsafe-inline'${isProduction ? "" : " 'unsafe-eval'"}`,
  "style-src 'self' 'unsafe-inline'",
  "img-src 'self' data: blob: https:" + (isProduction ? "" : " http:"),
  "font-src 'self'",
  `connect-src 'self'${isProduction ? "" : " ws: wss:"}`,
  `frame-src 'self'${siteOrigin ? ` ${siteOrigin}` : ""}`,
  "frame-ancestors 'none'",
  "form-action 'self'",
  "base-uri 'self'",
  "object-src 'none'",
].join("; ");

const securityHeaders = [
  { key: "Content-Security-Policy", value: contentSecurityPolicy },
  { key: "X-Content-Type-Options", value: "nosniff" },
  { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
  { key: "X-Frame-Options", value: "DENY" },
  {
    key: "Permissions-Policy",
    value: "camera=(), microphone=(), geolocation=()",
  },
  ...(isProduction
    ? [
        {
          key: "Strict-Transport-Security",
          value: "max-age=63072000; includeSubDomains",
        },
      ]
    : []),
];

const nextConfig: NextConfig = {
  poweredByHeader: false,
  // Pin the project root: this app lives inside the website's repository.
  turbopack: { root: __dirname },
  experimental: {
    serverActions: {
      // Article HTML plus FAQs (and JSON imports) can exceed the 1 MB default. Images upload through a route, not actions.
      bodySizeLimit: "4mb",
    },
  },
  async headers() {
    return [{ source: "/:path*", headers: securityHeaders }];
  },
  // Article HTML refers to images as "/uploads/…" (and "/blog-uploads/…" on
  // Laravel's local disk); load them from the CMS so the editor shows them.
  async rewrites() {
    return [
      { source: "/uploads/:path*", destination: `${cmsOrigin}/uploads/:path*` },
      {
        source: "/blog-uploads/:path*",
        destination: `${cmsOrigin}/blog-uploads/:path*`,
      },
    ];
  },
};

export default nextConfig;
