import react from "@vitejs/plugin-react";
import { createHash } from "crypto";
import { dirname, resolve } from "path";
import { fileURLToPath } from "url";
import { defineConfig, loadEnv, Plugin } from "vite";
import svgr from "vite-plugin-svgr";
import tsconfigPaths from "vite-tsconfig-paths";
import { vitePluginCspNonce } from "./vite-plugin-csp-nonce";
import { isLibPeerExternal } from "./vite.lib-peer-external";

const __dirname = dirname(fileURLToPath(import.meta.url));
const packageDir = __dirname;

// Plugin to inject build-time hash into context.js script tag
function contextJsHashPlugin(): Plugin {
  const buildHash = createHash("md5")
    .update(Date.now().toString())
    .update(process.pid?.toString() || "")
    .digest("hex")
    .substring(0, 8);

  return {
    name: "context-js-hash",
    transformIndexHtml(html) {
      return html.replace(
        /<script[^>]*src=["']\/context\.js[^"']*["'][^>]*><\/script>/i,
        `<script src="/context.js?v=${buildHash}"></script>`,
      );
    },
  };
}

// https://vite.dev/config/
export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, packageDir);
  const BASE_URL = env.VITE_PUBLIC_URL || "/";

  // Library build mode - creates npm package
  // Note: Type declarations (dts) disabled due to compatibility issues
  // Run `tsc --emitDeclarationOnly` separately if needed
  if (mode === "lib") {
    return {
      plugins: [react(), tsconfigPaths(), svgr()],
      build: {
        lib: {
          entry: resolve(__dirname, "src/index.ts"),
          name: "ConductorUI",
          fileName: "conductor-ui",
          formats: ["es"] as const,
        },
        rollupOptions: {
          external: isLibPeerExternal,
          output: {
            globals: {
              react: "React",
              "react-dom": "ReactDOM",
              "react-router-dom": "ReactRouterDOM",
            },
          },
        },
        sourcemap: true,
      },
    };
  }

  // App build mode - creates standalone OSS application
  return {
    base: BASE_URL,
    resolve: {
      // Prefer TypeScript so extensionless imports (e.g. `components/Foo`) resolve to
      // `Foo.tsx` when both TS and JS variants could apply.
      extensions: [".mjs", ".js", ".mts", ".ts", ".tsx", ".jsx", ".json"],
    },
    plugins: [
      react(),
      tsconfigPaths(),
      svgr(),
      vitePluginCspNonce(),
      contextJsHashPlugin(),
    ],
    optimizeDeps: {
      include: [
        "@emotion/react",
        "@emotion/styled",
        "@mui/material",
        "@mui/system",
      ],
    },
    define: {
      "process.env": {},
    },
    preview: {
      port: 1234,
      // Mirror the dev-server proxy so `vite preview` (used by integration
      // tests) forwards API calls to the Conductor backend.
      // VITE_WF_SERVER can be set in the process environment at preview time
      // to override the .env file value (e.g. for CI or Playwright webServer).
      proxy: {
        "/api": {
          target:
            process.env.VITE_WF_SERVER ||
            env.VITE_WF_SERVER ||
            "http://localhost:8080",
          changeOrigin: true,
        },
        "/swagger-ui": {
          target:
            process.env.VITE_WF_SERVER ||
            env.VITE_WF_SERVER ||
            "http://localhost:8080",
          changeOrigin: true,
        },
        "/api-docs": {
          target:
            process.env.VITE_WF_SERVER ||
            env.VITE_WF_SERVER ||
            "http://localhost:8080",
          changeOrigin: true,
        },
      },
    },
    server: {
      port: 1234,
      proxy: {
        "/api": {
          target: env.VITE_WF_SERVER || "http://localhost:8080",
          changeOrigin: true,
        },
        "/swagger-ui": {
          target: env.VITE_WF_SERVER || "http://localhost:8080",
          changeOrigin: true,
        },
        "/api-docs": {
          target: env.VITE_WF_SERVER || "http://localhost:8080",
          changeOrigin: true,
        },
      },
    },
    build: {
      outDir: "dist",
    },
    test: {
      globals: true,
      environment: "jsdom",
      setupFiles: "./src/setupTests.ts",
      include: ["src/**/*.test.{js,ts,jsx,tsx}"],
      coverage: {
        provider: "v8",
        reporter: ["text", "html", "lcov"],
        include: ["src/**/*.{ts,tsx}"],
        exclude: [
          "src/**/*.test.{ts,tsx}",
          "src/setupTests.ts",
          "src/main.tsx",
          "src/index.ts",
        ],
      },
      server: {
        deps: {
          // Force Vitest to process Monaco's ESM through its own pipeline
          // rather than trying to load browser-only bundles in jsdom.
          inline: ["monaco-editor"],
        },
      },
    },
  };
});
