import { builtinModules as builtins } from 'node:module';
import type { AstroIntegration } from 'astro';
import type { PluginOption } from 'vite';

export const resolveBuiltIns = (id: string) => {
	if (!id || id[0] === '.' || id[0] === '/') return;
	// Support already-namespaced ids and builtin subpaths (e.g., 'fs/promises').
	const plain = id.startsWith('node:') ? id.slice(5) : id;
	if (builtins.includes(plain)) {
		const namespaced = id.startsWith('node:') ? id : `node:${id}`;
		return { id: namespaced, external: true };
	}
	return;
};

/**
 * Creates an Astro integration that injects a Vite plugin to automatically
 * resolve Node.js built-in modules using the `node:` protocol namespace.
 *
 * This integration ensures that imports of Node.js built-ins (e.g., 'fs', 'path')
 * are rewritten to use the `node:` prefix and marked as external, preventing
 * bundling and ensuring correct module resolution in Vite-powered Astro projects.
 *
 * The integration checks if the 'namespace-builtins' Vite plugin is already present
 * before adding it, to avoid duplicate plugins.
 *
 * @returns {AstroIntegration} An Astro integration for handling Node.js built-in modules.
 */
export function nodeNamespaceBuiltinsAstro(): AstroIntegration {
	const name = 'studiocms/node-namespace-builtins';
	const plugin: PluginOption = {
		name,
		enforce: 'pre',
		resolveId: resolveBuiltIns,
	};
	return {
		name,
		hooks: {
			/* v8 ignore start */
			'astro:config:setup': (params) => {
				// Check if the 'namespace-builtins' plugin is already present
				const hasPlugin = params.config.vite?.plugins?.some(
					// biome-ignore lint/suspicious/noExplicitAny: Vite is fun
					(p) => p && typeof p === 'object' && (p as any).name === name
				);

				if (!hasPlugin) {
					params.updateConfig({
						vite: {
							plugins: [plugin],
						},
					});
				}
			},
			/* v8 ignore stop */
		},
	};
}
