import { regEx } from "../../../util/regex.js";
import { GlobalConfig } from "../../../config/global.js";
import { logger } from "../../../logger/index.js";
import { chmodLocalFile, readLocalFile, statLocalFile } from "../../../util/fs/index.js";
import api from "../../versioning/maven/index.js";
import { exec } from "../../../util/exec/index.js";
import { getRepoStatus } from "../../../util/git/index.js";
import { isTruthy } from "@sindresorhus/is";
import upath from "upath";
import os from "node:os";

//#region lib/modules/manager/maven-wrapper/artifacts.ts
const DEFAULT_MAVEN_REPO_URL = "https://repo.maven.apache.org/maven2";
async function addIfUpdated(status, fileProjectPath) {
	if (status.modified.includes(fileProjectPath)) return { file: {
		type: "addition",
		path: fileProjectPath,
		contents: await readLocalFile(fileProjectPath)
	} };
	return null;
}
async function updateArtifacts({ packageFileName, updatedDeps, config }) {
	try {
		logger.debug({ updatedDeps }, "maven-wrapper.updateArtifacts()");
		if (!updatedDeps.some((dep) => dep.depName === "maven-wrapper")) {
			logger.info("Maven wrapper version not updated - skipping Artifacts update");
			return null;
		}
		const cmd = await createWrapperCommand(packageFileName);
		if (!cmd) {
			logger.info("No mvnw found - skipping Artifacts update");
			return null;
		}
		await executeWrapperCommand(cmd, config, packageFileName, getExtraEnvOptions(updatedDeps));
		const updateArtifactsResult = (await getUpdatedArtifacts(await getRepoStatus(), [
			".mvn/wrapper/maven-wrapper.properties",
			".mvn/wrapper/maven-wrapper.jar",
			".mvn/wrapper/MavenWrapperDownloader.java",
			"mvnw",
			"mvnw.cmd"
		].map((filename) => packageFileName.replace(".mvn/wrapper/maven-wrapper.properties", "") + filename))).filter(isTruthy);
		logger.debug({ files: updateArtifactsResult.map((r) => r.file?.path) }, `Returning updated maven-wrapper files`);
		return updateArtifactsResult;
	} catch (err) {
		logger.debug({ err }, "Error setting new Maven Wrapper release value");
		return [{ artifactError: {
			lockFile: packageFileName,
			stderr: err.message
		} }];
	}
}
async function getUpdatedArtifacts(status, artifactFileNames) {
	const updatedResults = [];
	for (const artifactFileName of artifactFileNames) {
		const updatedResult = await addIfUpdated(status, artifactFileName);
		if (updatedResult !== null) updatedResults.push(updatedResult);
	}
	return updatedResults;
}
/**
* Find compatible java version for maven.
* see https://maven.apache.org/developers/compatibility-plan.html
* @param mavenWrapperVersion current maven version
* @returns A Java semver range
*/
function getJavaConstraint(mavenWrapperVersion) {
	const major = mavenWrapperVersion ? api.getMajor(mavenWrapperVersion) : null;
	if (major && major >= 3) return "^17.0.0";
	return "^8.0.0";
}
async function executeWrapperCommand(cmd, config, packageFileName, extraEnv) {
	logger.debug(`Updating maven wrapper: "${cmd}"`);
	const { wrapperFullyQualifiedPath } = getMavenPaths(packageFileName);
	const execOptions = {
		cwdFile: wrapperFullyQualifiedPath,
		docker: {},
		extraEnv,
		toolConstraints: [{
			toolName: "java",
			constraint: config.constraints?.java ?? getJavaConstraint(config.currentValue)
		}]
	};
	try {
		await exec(cmd, execOptions);
	} catch (err) {
		logger.error({ err }, "Error executing maven wrapper update command.");
		throw err;
	}
}
function getExtraEnvOptions(deps) {
	const customMavenWrapperUrl = getCustomMavenWrapperRepoUrl(deps);
	if (customMavenWrapperUrl) return { MVNW_REPOURL: customMavenWrapperUrl };
	return {};
}
function getCustomMavenWrapperRepoUrl(deps) {
	const replaceString = deps.find((dep) => dep.depName === "maven-wrapper")?.replaceString;
	if (!replaceString) return null;
	const match = regEx(/^(.*?)\/org\/apache\/maven\/wrapper\//).exec(replaceString);
	if (!match) return null;
	return match[1] === DEFAULT_MAVEN_REPO_URL ? null : match[1];
}
async function createWrapperCommand(packageFileName) {
	const { wrapperExecutableFileName, localProjectDir, wrapperFullyQualifiedPath } = getMavenPaths(packageFileName);
	return await prepareCommand(wrapperExecutableFileName, localProjectDir, await statLocalFile(wrapperFullyQualifiedPath), "wrapper:wrapper");
}
function mavenWrapperFileName() {
	if (os.platform() === "win32" && GlobalConfig.get("binarySource") !== "docker") return "mvnw.cmd";
	return "./mvnw";
}
function getMavenPaths(packageFileName) {
	const wrapperExecutableFileName = mavenWrapperFileName();
	const localProjectDir = upath.join(upath.dirname(packageFileName), packageFileName.includes("mvnw") ? "." : "../../");
	return {
		wrapperExecutableFileName,
		localProjectDir,
		wrapperFullyQualifiedPath: upath.join(localProjectDir, wrapperExecutableFileName)
	};
}
async function prepareCommand(fileName, cwd, pathFileStats, args) {
	/* v8 ignore next -- hard to test */
	if (pathFileStats?.isFile() === true) {
		if (os.platform() !== "win32" && (pathFileStats.mode & 1) === 0) {
			logger.warn("Maven wrapper is missing the executable bit");
			await chmodLocalFile(upath.join(cwd, fileName), pathFileStats.mode | 73);
		}
		if (args === null) return fileName;
		return `${fileName} ${args}`;
	}
	return null;
}

//#endregion
export { updateArtifacts };
//# sourceMappingURL=artifacts.js.map