import path from "path";
import fs from "fs";
//#region src/shared/stringCase.ts
function toPascalCase(str) {
	return `${str}`.toLowerCase().replace(/[-_]+/g, " ").replace(/[^\w\s]/g, "").replace(/\s+(.)(\w*)/g, (_m, a, b) => `${a.toUpperCase()}${b}`).replace(/\w/, (s) => s.toUpperCase());
}
//#endregion
//#region src/shared/hostBootstrap.ts
/**
* Host plugin bootstrap: sets contractual `window.__ns__.publicPath` (e.g. `/product/`)
* before product entry runs. Publish bootstrap uses script/meta detection only when
* `publicPath` is still unset — plugin-dev must rely on host prepend, not detection.
*/
function createNormalizedPublicPathAssignment(environmentVariable, rawPath) {
	const literal = JSON.stringify(String(rawPath || ""));
	return [
		`if (!window.${environmentVariable}.publicPath) window.${environmentVariable}.publicPath = (function() {`,
		`  var rawPath = ${literal};`,
		"  if (!rawPath) {",
		"    rawPath = './';",
		"  }",
		"  try {",
		"    var normalizedPath = String(rawPath);",
		"    if (/^[a-zA-Z][a-zA-Z\\d+\\-.]*:/.test(normalizedPath) || normalizedPath.indexOf('//') === 0) {",
		"      return normalizedPath;",
		"    }",
		"    var baseUrl = typeof document !== 'undefined' && document.baseURI",
		"      ? document.baseURI",
		"      : (typeof window !== 'undefined' && window.location ? window.location.href : '');",
		"    return baseUrl ? new URL(normalizedPath, baseUrl).href : normalizedPath;",
		"  } catch (_error) {",
		"    return String(rawPath);",
		"  }",
		"})();"
	].join(" ");
}
function createInitFragment(environmentVariable, publicPath, startupPrefetchMode) {
	return [
		`window.${environmentVariable} = window.${environmentVariable} || {};`,
		createNormalizedPublicPathAssignment(environmentVariable, publicPath),
		`if (!window.${environmentVariable}.startupPrefetchMode) window.${environmentVariable}.startupPrefetchMode = "${startupPrefetchMode}";`
	].join(" ");
}
//#endregion
//#region src/shared/hostPackageEntryMatch.ts
/**
* Match main product entry modules for host bootstrap injection (Vite + Webpack).
* Uses suffix matching so absolute node_modules ids ending with `{packagePath}/{appName}-esm.js`
* match the same way as Webpack `renderModuleContent` (endsWith), not exact relative paths.
*/
function normalizeHostModulePath(value) {
	return String(value || "").replace(/#.*$/s, "").replace(/\?.*$/s, "").replace(/\\/g, "/");
}
function getProductEntrySuffixes(packagePath, appName) {
	return [
		`${packagePath}/${appName}-esm.js`,
		`${packagePath}/${appName}.js`,
		`${packagePath.replace(/[\\/]/g, "_")}.js`
	].map(normalizeHostModulePath);
}
function shouldMatchProductPackageEntry(moduleId, packagePath, appName, optimizedDepFileName) {
	const normalized = normalizeHostModulePath(moduleId);
	if (!normalized) return false;
	if (getProductEntrySuffixes(packagePath, appName).some((suffix) => normalized === suffix || normalized.endsWith(`/${suffix}`))) return true;
	if (optimizedDepFileName) {
		const depName = normalizeHostModulePath(optimizedDepFileName);
		return normalized.includes("/.vite/deps/") && normalized.endsWith(`/${depName}`);
	}
	return false;
}
//#endregion
//#region src/shared/branding.ts
/**
* Чтение `process.env.REACT_APP_*` — как в основном приложении.
* На этапе сборки `build.ts` подставляет в `define` итоговые строки (см. `bundlerDefines()`).
*/
var BUNDLER_DEFAULT_PACKAGE_NAME = "useblocks";
var BUNDLER_DEFAULT_APP_NAME = "useblocks";
`${BUNDLER_DEFAULT_APP_NAME}`;
//#endregion
//#region src/webpack/index.ts
var PLUGIN_NAME = `${toPascalCase(BUNDLER_DEFAULT_APP_NAME)}WebpackPlugin`;
var PACKAGE_ENTRY_NAME = `${BUNDLER_DEFAULT_APP_NAME}.js`;
var ESM_PACKAGE_ENTRY_NAME = `${BUNDLER_DEFAULT_APP_NAME}-esm.js`;
var DEFAULT_OUTPUT_FOLDER = BUNDLER_DEFAULT_APP_NAME;
var DEFAULT_MODULES_PATH = "node_modules";
var DEFAULT_STARTUP_PREFETCH_MODE = "eager";
var ENVIRONMENT_VARIABLE = `__${BUNDLER_DEFAULT_APP_NAME}__`;
var IGNORED_PATTERNS = [
	/.*\.npmignore/,
	/.*\.gitignore/,
	/.*\.md$/,
	/.*\.ts$/,
	/.*\.d\.ts$/,
	/.*\.json$/,
	/.*\.ico$/,
	/.*\.pot$/,
	/^.*(?<!iframe\..{1,})\.html$/,
	/vite\?.*$/,
	/webpack\?.*$/,
	/react\?.*$/,
	/robots.txt$/,
	/main\..*\.js$/,
	/.*\\sandbox-eblock.*$/,
	new RegExp(PACKAGE_ENTRY_NAME.replace(/\./g, "\\.") + "$"),
	new RegExp(ESM_PACKAGE_ENTRY_NAME.replace(/\./g, "\\.") + "$"),
	/\.js\.map$/
];
function toAssetPath(...segments) {
	return segments.flatMap((segment) => String(segment || "").split(/[\\/]+/)).filter(Boolean).join("/");
}
function getWebpackModulePath(module) {
	if (!module) return;
	if (typeof module.resource === "string" && module.resource) return module.resource;
	const name = typeof module.nameForCondition === "function" ? module.nameForCondition() : null;
	return typeof name === "string" && name ? name : void 0;
}
function getModuleSourceCode(source) {
	if (source && typeof source === "object" && "source" in source && typeof source.source === "function") return source.source();
	return String(source ?? "");
}
function shouldInjectRuntimeBootstrap(modulePath) {
	return shouldMatchProductPackageEntry(modulePath || "", BUNDLER_DEFAULT_PACKAGE_NAME, BUNDLER_DEFAULT_APP_NAME);
}
/**
* Webpack plugin for host applications.
* Copies static assets (images, iframe, fonts, monaco workers) to the build output
* and injects publicPath into the entry module so the editor can locate them at runtime.
* The thin facade entry is still handled by the consumer bundler, while
* browser-loaded core assets are copied to the host output and served from publicPath.
*
* For plugin development (externals + alias), use a separate plugin
* from the `webpack/pluginDev` subpath.
*/
var WebpackPlugin = class {
	constructor(options = {}) {
		this._outputFolder = DEFAULT_OUTPUT_FOLDER;
		this._modulesPath = DEFAULT_MODULES_PATH;
		this._publicPath = void 0;
		this._startupPrefetchMode = DEFAULT_STARTUP_PREFETCH_MODE;
		this._sources = null;
		if (options.outputFolder !== void 0) this._outputFolder = options.outputFolder;
		if (options.modulesPath !== void 0) this._modulesPath = options.modulesPath;
		if (options.publicPath !== void 0) this._publicPath = options.publicPath;
		if (options.startupPrefetchMode !== void 0) this._startupPrefetchMode = options.startupPrefetchMode;
	}
	async addAsset(compilation, sourcePath, destPath) {
		const filePath = path.resolve(compilation.compiler.context, sourcePath);
		if (IGNORED_PATTERNS.some((pattern) => pattern.test(filePath))) return;
		if (!compilation.getAsset(destPath)) {
			const [stat, data] = await Promise.all([fs.promises.stat(filePath), fs.promises.readFile(filePath)]);
			const { size } = stat;
			const source = new (this._sources || compilation.compiler.webpack.sources).RawSource(data);
			compilation.emitAsset(destPath, source, { size });
		}
	}
	async copyFiles(compilation, source, destination) {
		const directoryEntries = await fs.promises.readdir(source, { withFileTypes: true });
		await Promise.all(directoryEntries.map(async (entry) => {
			const sourcePath = path.join(source, entry.name);
			const destinationPath = toAssetPath(destination, entry.name);
			return entry.isDirectory() ? this.copyFiles(compilation, sourcePath, destinationPath) : this.addAsset(compilation, sourcePath, destinationPath);
		}));
	}
	apply(compiler) {
		const rawPub = compiler.options.output.publicPath;
		const optionsPublicPath = typeof rawPub === "string" ? rawPub : "";
		const publicPath = this._publicPath === void 0 ? optionsPublicPath : this._publicPath;
		const initFragment = createInitFragment(ENVIRONMENT_VARIABLE, publicPath + (publicPath.endsWith("/") ? "" : "/") + this._outputFolder + "/", this._startupPrefetchMode);
		const webpack = compiler.webpack;
		const javascript = webpack.javascript;
		this._sources = webpack.sources;
		compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
			compilation.hooks.processAssets.tapAsync({
				name: PLUGIN_NAME,
				stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
			}, async (_unusedAssets, cb) => {
				try {
					await this.copyFiles(compilation, path.join(this._modulesPath, BUNDLER_DEFAULT_PACKAGE_NAME), this._outputFolder);
					cb(null);
				} catch (error) {
					cb(error);
				}
			});
			javascript.JavascriptModulesPlugin.getCompilationHooks(compilation).renderModuleContent.tap(PLUGIN_NAME, (source, module) => {
				if (shouldInjectRuntimeBootstrap(getWebpackModulePath(module))) {
					const sources = this._sources || compilation.compiler.webpack.sources;
					const patched = `${initFragment}\n${getModuleSourceCode(source)}`;
					return new sources.RawSource(patched);
				}
				return source;
			});
		});
	}
};
//#endregion
export { WebpackPlugin as default };
