/// <reference types="vitest/config" />

import { existsSync, readFileSync, writeFileSync } from "node:fs"
import path from "node:path"
import tailwindcss from "@tailwindcss/vite"
import react from "@vitejs/plugin-react-swc"
import { resolve } from "path"
import { defineConfig, type Plugin, ViteDevServer } from "vite"

// Mirror the esbuild.mjs .env loader: read the workspace-root .env so that
// build-time vars (telemetry keys, IS_DEV, …) reach vite even though vite runs
// from webview-ui/. Shell-exported vars take precedence (only fills missing).
const rootEnvPath = path.join(__dirname, "..", ".env")
if (existsSync(rootEnvPath)) {
	for (const line of readFileSync(rootEnvPath, "utf8").split(/\r?\n/)) {
		const match = line.match(/^\s*([A-Z_][A-Z0-9_]*)\s*=\s*(.*?)\s*$/i)
		if (match && !process.env[match[1]]) {
			process.env[match[1]] = match[2].replace(/^["']|["']$/g, "")
		}
	}
}

// Custom plugin to write the server port to a file
const writePortToFile = (): Plugin => {
	return {
		name: "write-port-to-file",
		configureServer(server: ViteDevServer) {
			server.httpServer?.once("listening", () => {
				const address = server.httpServer?.address()
				const port = typeof address === "object" && address ? address.port : null

				if (port) {
					const portFilePath = resolve(__dirname, ".vite-port")
					writeFileSync(portFilePath, port.toString())
				} else {
					console.warn("[writePortToFile] Could not determine server port")
				}
			})
		},
	}
}

const isDevBuild = process.argv.includes("--dev-build")

// Valid platforms, these should the keys in platform-configs.json
const VALID_PLATFORMS = ["vscode", "standalone"]
const platform = process.env.PLATFORM || "vscode" // Default to vscode

if (!VALID_PLATFORMS.includes(platform)) {
	throw new Error(`Invalid PLATFORM "${platform}". Must be one of: ${VALID_PLATFORMS.join(", ")}`)
}
console.log("Building webview for", platform)

export default defineConfig({
	optimizeDeps: {
		force: true, // Forces re-optimization
	},
	plugins: [react(), tailwindcss(), writePortToFile()],
	test: {
		environment: "jsdom",
		globals: true,
		setupFiles: ["./src/setupTests.ts"],
		coverage: {
			provider: "v8",
			reportOnFailure: true,
			reporter: ["html", "lcov", "text"],
			reportsDirectory: "./coverage",
			exclude: [
				"**/*.{spec,test}.{js,jsx,ts,tsx,mjs,cjs}",

				"**/*.d.ts",
				"**/vite-env.d.ts",
				"**/*.{config,setup}.{js,ts,mjs,cjs}",

				"**/*.{css,scss,sass,less,styl}",
				"**/*.{svg,png,jpg,jpeg,gif,ico}",

				"**/*.{json,yaml,yml}",

				"**/__mocks__/**",
				"node_modules/**",
				"build/**",
				"coverage/**",
				"dist/**",
				"public/**",

				"src/services/grpc-client.ts",
			],
		},
	},
	build: {
		outDir: "build",
		reportCompressedSize: false,
		// Inline ALL font files as base64 data URIs instead of emitting them as
		// separate asset files. VS Code webviews load resources through
		// `asWebviewUri()`; an external `url(/assets/codicon.ttf)` reference
		// resolves to the webview origin root and 404s, so codicons render as
		// blank squares and the azeret code font falls back to a system font.
		// Inlining sidesteps URL resolution entirely (the CSP already allows
		// `data:` in `font-src`) and removes separate font fetches from the load
		// path. This replaces the reverted `base: "./"` approach, which rewrote
		// *all* asset URLs globally and caused an intermittent webview hang —
		// inlining touches only fonts.
		assetsInlineLimit: (filePath: string) => (/\.(ttf|woff2?|eot)$/.test(filePath) ? true : undefined),
		// Only minify in production build
		minify: !isDevBuild,
		// Enable inline source maps for dev build
		sourcemap: isDevBuild ? "inline" : false,
		rollupOptions: {
			output: {
				inlineDynamicImports: true,
				entryFileNames: `assets/[name].js`,
				chunkFileNames: `assets/[name].js`,
				assetFileNames: `assets/[name].[ext]`,
				// Disable compact output for dev build
				compact: !isDevBuild,
				// Add generous formatting for dev build
				...(isDevBuild && {
					generatedCode: {
						constBindings: false,
						objectShorthand: false,
						arrowFunctions: false,
					},
				}),
			},
		},
		chunkSizeWarningLimit: 100000,
	},
	server: {
		port: 25463,
		hmr: {
			host: "localhost",
			protocol: "ws",
		},
		cors: {
			origin: "*",
			methods: "*",
			allowedHeaders: "*",
		},
	},
	define: {
		__PLATFORM__: JSON.stringify(platform),
		process: JSON.stringify({
			platform: JSON.stringify(process?.platform),
			env: {
				NODE_ENV: JSON.stringify(process?.env?.IS_DEV ? "development" : "production"),
				CLINE_ENVIRONMENT: JSON.stringify(process?.env?.CLINE_ENVIRONMENT ?? "production"),
				IS_DEV: JSON.stringify(process?.env?.IS_DEV),
				IS_TEST: JSON.stringify(process?.env?.IS_TEST),
				CI: JSON.stringify(process?.env?.CI),
				// PostHog environment variables
				TELEMETRY_SERVICE_API_KEY: JSON.stringify(process?.env?.TELEMETRY_SERVICE_API_KEY),
				ERROR_SERVICE_API_KEY: JSON.stringify(process?.env?.ERROR_SERVICE_API_KEY),
			},
		}),
	},
	resolve: {
		alias: {
			"@": resolve(__dirname, "./src"),
			"@components": resolve(__dirname, "./src/components"),
			"@context": resolve(__dirname, "./src/context"),
			"@shared": resolve(__dirname, "../src/shared"),
			"@utils": resolve(__dirname, "./src/utils"),
		},
	},
})
