import { appTools, defineConfig } from "@modern-js/app-tools";
import { moduleFederationPlugin } from "@module-federation/modern-js";

const buildTarget = process.env["BUILD_TARGET"];
const isRemote = buildTarget === "remote";

// Runtime env values that must reach the client bundle. Rspack resolves
// `process.env` at BUILD time to an empty-ish polyfill in the browser, so
// any value we want per-deployment (e.g. MAP_TILE_URL pointing at a tile
// service that the local ingress doesn't proxy) has to be injected into
// the HTML as a window global. getEnv() picks up window.__ENV__ on the
// client. Evaluated once at Modern.js build time → pod env → HTML.
//
// IMPORTANT: Rspack's HTML plugin preprocesses <script> children through
// a template engine that eats '{token}' pairs AND decodes \u007B / \u007D
// Unicode escapes before running the engine, so neither raw braces nor
// escaped braces survive. The Leaflet tile template literally contains
// '{z}/{x}/{y}', so we serialize the whole payload to base64 and decode
// it in the browser at runtime. Base64 output is A-Z/a-z/0-9/+/=/ — no
// braces for the template engine to grab.
const PUBLIC_ENV_KEYS = ["MAP_TILE_URL", "API_BASE_URL", "SIGNALR_HUB_URL"] as const;
const PUBLIC_ENV: Record<string, string> = {};
for (const k of PUBLIC_ENV_KEYS) {
  const v = process.env[k];
  if (typeof v === "string" && v.length > 0) PUBLIC_ENV[k] = v;
}
const publicEnvB64 = Buffer.from(
  JSON.stringify(PUBLIC_ENV),
  "utf8",
).toString("base64");
// Pure-expression form — NO '{' or '}' anywhere in the source. The
// base64 payload round-trips `{…}` without exposing braces to the
// Rspack HTML plugin. `Object.create(null)` replaces an empty `{}`.
const PUBLIC_ENV_SCRIPT =
  `window.__ENV__=Object.assign(window.__ENV__||Object.create(null),JSON.parse(atob("${publicEnvB64}")));`;

export default defineConfig({
  plugins: [appTools({ bundler: "rspack" }), moduleFederationPlugin()],
  source: {
    entriesDir: "./src",
  },
  html: {
    favicon: "./config/public/favicon.ico",
    tags: [
      // Inline script runs before the main bundle so client-side getEnv()
      // sees the pod's env (read when the SSR server starts).
      {
        tag: "script",
        head: true,
        append: false,
        children: PUBLIC_ENV_SCRIPT,
      },
      {
        tag: "link",
        attrs: {
          rel: "icon",
          type: "image/png",
          sizes: "32x32",
          href: "/assets/img/favicon-32x32.png",
        },
      },
      {
        tag: "link",
        attrs: {
          rel: "icon",
          type: "image/png",
          sizes: "16x16",
          href: "/assets/img/favicon-16x16.png",
        },
      },
      {
        tag: "link",
        attrs: {
          rel: "apple-touch-icon",
          href: "/assets/img/favicon-touch.png",
        },
      },
    ],
  },
  runtime: {
    router: {
      future: {
        v7_startTransition: true,
        v7_relativeSplatPath: true,
        v7_fetcherPersist: true,
        v7_normalizeFormMethod: true,
        v7_partialHydration: true,
        v7_skipActionErrorRevalidation: true,
      },
    },
  },
  server: {
    ssr: {
      mode: "stream",
    },
  },
  tools: {
    cssLoader: {
      url: false,
    },
    // Explicit dev-server CORS headers. Silences the MF modern-js warning
    // about empty devServer.headers (auto-assigning "*"). Production is
    // unaffected — the real reverse proxy manages CORS.
    devServer: {
      headers: {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Headers":
          "Content-Type, Authorization, Accept, Accept-Language",
        "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
      },
    },
  },
  output: {
    distPath: { root: isRemote ? "dist/remote" : "dist/standalone" },
  },
});
