import { NO_VULNERABILITY_ALERTS } from "../../../constants/error-messages.js";
import { logger } from "../../../logger/index.js";
import { id } from "../../../modules/versioning/pep440/index.js";
import { id as id$1 } from "../../../modules/versioning/semver/index.js";
import { id as id$2 } from "../../../modules/versioning/npm/index.js";
import { NpmDatasource } from "../../../modules/datasource/npm/index.js";
import { PypiDatasource } from "../../../modules/datasource/pypi/index.js";
import { id as id$3 } from "../../../modules/versioning/ruby/index.js";
import { GoDatasource } from "../../../modules/datasource/go/index.js";
import { id as id$4 } from "../../../modules/versioning/maven/index.js";
import { MavenDatasource } from "../../../modules/datasource/maven/index.js";
import { id as id$5 } from "../../../modules/versioning/composer/index.js";
import { get } from "../../../modules/versioning/index.js";
import { CrateDatasource } from "../../../modules/datasource/crate/index.js";
import { NugetDatasource } from "../../../modules/datasource/nuget/index.js";
import { PackagistDatasource } from "../../../modules/datasource/packagist/index.js";
import { RubygemsDatasource } from "../../../modules/datasource/rubygems/index.js";
import { platform } from "../../../modules/platform/index.js";
import { sanitizeMarkdown } from "../../../util/markdown.js";

//#region lib/workers/repository/init/vulnerability.ts
async function detectVulnerabilityAlerts(input) {
	if (!input?.vulnerabilityAlerts) return input;
	if (input.vulnerabilityAlerts.enabled === false) {
		logger.debug("Vulnerability alerts are disabled");
		return input;
	}
	const alerts = await platform.getVulnerabilityAlerts?.();
	if (!alerts?.length) {
		logger.debug("No vulnerability alerts found");
		if (input.vulnerabilityAlertsOnly) throw new Error(NO_VULNERABILITY_ALERTS);
		return input;
	}
	const config = { ...input };
	const versionings = {
		"github-tags": id$1,
		go: id$1,
		packagist: id$5,
		maven: id$4,
		npm: id$2,
		nuget: id$1,
		pypi: id,
		rubygems: id$3
	};
	const combinedAlerts = {};
	for (const alert of alerts) try {
		if (alert.dismissed_reason) continue;
		if (!alert.security_vulnerability?.first_patched_version) {
			logger.debug({ alert }, "Vulnerability alert has no firstPatchedVersion - skipping");
			continue;
		}
		const datasource = {
			composer: PackagistDatasource.id,
			go: GoDatasource.id,
			maven: MavenDatasource.id,
			npm: NpmDatasource.id,
			nuget: NugetDatasource.id,
			pip: PypiDatasource.id,
			rubygems: RubygemsDatasource.id,
			rust: CrateDatasource.id
		}[alert.security_vulnerability.package.ecosystem];
		const depName = alert.security_vulnerability.package.name;
		const fileName = alert.dependency.manifest_path;
		const fileType = fileName.split("/").pop();
		const firstPatchedVersion = alert.security_vulnerability.first_patched_version.identifier;
		const advisory = alert.security_advisory;
		combinedAlerts[fileName] ??= {};
		combinedAlerts[fileName][datasource] ??= {};
		combinedAlerts[fileName][datasource][depName] ??= { advisories: [] };
		const alertDetails = combinedAlerts[fileName][datasource][depName];
		alertDetails.advisories.push(advisory);
		const versioningApi = get(versionings[datasource]);
		if (versioningApi.isVersion(firstPatchedVersion)) {
			if (!alertDetails.firstPatchedVersion || versioningApi.isGreaterThan(firstPatchedVersion, alertDetails.firstPatchedVersion)) alertDetails.firstPatchedVersion = firstPatchedVersion;
		} else logger.debug("Invalid firstPatchedVersion: " + firstPatchedVersion);
		alertDetails.fileType = fileType;
	} catch (err) {
		logger.warn({ err }, "Error parsing vulnerability alert");
	}
	const alertPackageRules = [];
	config.remediations = {};
	for (const [fileName, files] of Object.entries(combinedAlerts)) for (const [datasource, dependencies] of Object.entries(files)) for (const [depName, val] of Object.entries(dependencies)) {
		let prBodyNotes = [];
		try {
			prBodyNotes = ["### GitHub Vulnerability Alerts"].concat(val.advisories.map((advisory) => {
				const identifiers = advisory.identifiers;
				const description = advisory.description;
				let content = "#### ";
				let heading;
				if (identifiers.some((id) => id.type === "CVE")) heading = identifiers.filter((id) => id.type === "CVE").map((id) => id.value).join(" / ");
				else heading = identifiers.map((id) => id.value).join(" / ");
				if (advisory.references?.length) heading = `[${heading}](${advisory.references[0].url})`;
				content += heading;
				content += "\n\n";
				content += sanitizeMarkdown(description);
				return content;
			}));
		} catch (err) 		/* istanbul ignore next */ {
			logger.warn({ err }, "Error generating vulnerability PR notes");
		}
		const matchFileNames = datasource === GoDatasource.id ? [fileName.replace("go.sum", "go.mod")] : [fileName];
		let matchRule = {
			matchDatasources: [datasource],
			matchPackageNames: [depName],
			matchFileNames
		};
		let matchCurrentVersion = `< ${val.firstPatchedVersion}`;
		if (datasource === MavenDatasource.id || datasource === NugetDatasource.id) matchCurrentVersion = `(,${val.firstPatchedVersion})`;
		matchRule = {
			...matchRule,
			matchCurrentVersion,
			vulnerabilityFixVersion: val.firstPatchedVersion,
			prBodyNotes,
			isVulnerabilityAlert: true,
			force: { ...config.vulnerabilityAlerts }
		};
		alertPackageRules.push(matchRule);
	}
	logger.debug({ alertPackageRules }, "alert package rules");
	config.packageRules = (config.packageRules ?? []).concat(alertPackageRules);
	return config;
}

//#endregion
export { detectVulnerabilityAlerts };
//# sourceMappingURL=vulnerability.js.map