import fs from "fs";
import path from "path";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";
import { defineConfig, loadEnv } from "vite";

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), "");

  // Same-origin sub-path the host server serves the module from. `base` makes
  // built asset URLs resolve under it AND is read back inside the module
  // (import.meta.env.BASE_URL) to set the router basename. Override with UM_BASE.
  const base = env.UM_BASE || "/_um/";

  // Build straight into the host app's public dir so its ONE server serves the
  // module at <origin>/_um/ — no second server, same origin as the host.
  const outDir = path.resolve(__dirname, "../public/_um");

  return {
    base,
    plugins: [
      tailwindcss(),
      react(),
      {
        // TinyMCE is self-hosted; the module references it at the ABSOLUTE path
        // /tinymce/..., which resolves at the host origin. Mirror the assets into
        // BOTH the module public dir AND the host public root. Regenerated on
        // build, so neither copy is a hand-managed artifact.
        name: "copy-tinymce-assets",
        buildStart() {
          const src = path.resolve(__dirname, "node_modules/tinymce");
          const dests = [
            path.resolve(__dirname, "../user-management/public/tinymce"),
            path.resolve(__dirname, "../public/tinymce"),
          ];
          const runtimeEntries = [
            "tinymce.min.js",
            "icons",
            "models",
            "plugins",
            "skins",
            "themes",
          ];

          if (!fs.existsSync(src)) {
            throw new Error(
              "[copy-tinymce-assets] node_modules/tinymce not found in this app. Run `npm install` here first."
            );
          }

          for (const dest of dests) {
            fs.mkdirSync(dest, { recursive: true });
            for (const entry of runtimeEntries) {
              const entrySrc = path.resolve(src, entry);
              const entryDest = path.resolve(dest, entry);
              if (!fs.existsSync(entrySrc)) continue;
              fs.cpSync(entrySrc, entryDest, { recursive: true, force: true });
            }
          }
        },
      },
    ],
    assetsInclude: ["**/*.TTF"],
    // Static assets (incl. tinymce/) live in the module's public dir.
    publicDir: path.resolve(__dirname, "../user-management/public"),
    build: {
      rollupOptions: {
        external: [
          "file-type",
          "readable-web-to-node-stream",
          "strtok3",
          "token-types",
        ],
      },
      outDir,
      assetsDir: "assets",
      sourcemap: false,
      emptyOutDir: true,
      minify: "esbuild",
    },
    resolve: {
      alias: [
        // @app-config = this host folder itself (project.theme.ts / fhc.theme.ts).
        { find: /^@app-config\//, replacement: path.resolve(__dirname) + "/" },
        // @/ = the reusable module's source in the SIBLING module folder.
        { find: /^@\//, replacement: path.resolve(__dirname, "../user-management/src") + "/" },
      ],
      // node_modules is linked to the module's, but pin the singletons so the host
      // entry and the module code share ONE React 18 (no "invalid hook call").
      dedupe: ["react", "react-dom", "react-router-dom", "@tanstack/react-query", "@mantine/core", "@mantine/hooks"],
    },
    server: {
      port: env.DEV_PORT ? Number(env.DEV_PORT) : 5173,
      strictPort: true,
      fs: { allow: [path.resolve(__dirname, "..")] },
    },
    optimizeDeps: {
      exclude: ["file-type", "readable-web-to-node-stream", "strtok3", "token-types"],
    },
    esbuild: {
      drop: mode === "production" ? ["console", "debugger"] : [],
    },
    define: {
      global: {},
    },
  };
});
