import { REPOSITORY_CLOSED_ONBOARDING } from "../../../../constants/error-messages.js";
import { GlobalConfig } from "../../../../config/global.js";
import { logger } from "../../../../logger/index.js";
import { getInheritedOrGlobal } from "../../../../util/common.js";
import { compile } from "../../../../util/template/index.js";
import { toSha256 } from "../../../../util/hash.js";
import { getFile } from "../../../../util/git/index.js";
import { getElapsedDays } from "../../../../util/date.js";
import { emojify } from "../../../../util/emoji.js";
import { hashBody } from "../../../../modules/platform/pr-body.js";
import { scm } from "../../../../modules/platform/scm.js";
import { platform } from "../../../../modules/platform/index.js";
import { isOnboardingBranchConflicted } from "../branch/onboarding-branch-cache.js";
import { OnboardingState, getDefaultConfigFileName, getSemanticCommitPrTitle } from "../common.js";
import { ensureComment } from "../../../../modules/platform/comment.js";
import { getDepWarningsOnboardingPR, getErrors, getWarnings } from "../../errors-warnings.js";
import { prepareLabels } from "../../update/pr/labels.js";
import { addParticipants } from "../../update/pr/participants.js";
import { getPlatformPrOptions } from "../../update/pr/index.js";
import { getBaseBranchDesc } from "./base-branch.js";
import { getConfigDesc } from "./config-description.js";
import { getExpectedPrList } from "./pr-list.js";
import { isNumber, isString } from "@sindresorhus/is";
//#region lib/workers/repository/onboarding/pr/index.ts
/**
* Given an existing PR, if onboardingAutoCloseAge has passed, close the PR.
*
* Returns true if the PR was closed.
*/
async function ensureOnboardingAutoCloseAge(existingPr) {
	const ageOfOnboardingPr = getElapsedDays(existingPr.createdAt, false);
	const onboardingAutoCloseAge = getInheritedOrGlobal("onboardingAutoCloseAge");
	if (onboardingAutoCloseAge) logger.debug({
		onboardingAutoCloseAge,
		createdAt: existingPr.createdAt,
		ageOfOnboardingPr
	}, `Determining that the onboarding PR created at \`${existingPr.createdAt}\` was created ${ageOfOnboardingPr.toFixed(2)} days ago`);
	if (isNumber(onboardingAutoCloseAge) && ageOfOnboardingPr > onboardingAutoCloseAge) {
		await platform.updatePr({
			number: existingPr.number,
			state: "closed",
			prTitle: existingPr.title
		});
		await ensureComment({
			number: existingPr.number,
			topic: `Renovate is disabled`,
			content: `Renovate is disabled because the onboarding PR has been unmerged for more than ${onboardingAutoCloseAge} days. To enable Renovate, you can either (a) change this PR's title to get a new onboarding PR, and merge the new onboarding PR, or (b) create a Renovate config file, and commit that file to your base branch.`
		});
		logger.debug({
			ageOfOnboardingPr,
			onboardingAutoCloseAge
		}, `Renovate is being disabled for this repository as the onboarding PR has been unmerged for more than ${onboardingAutoCloseAge} days`);
		return true;
	}
	return false;
}
async function ensureOnboardingPr(config, packageFiles, branches) {
	if (config.repoIsOnboarded === true || config.onboardingRebaseCheckbox && !OnboardingState.prUpdateRequested) return;
	logger.debug("ensureOnboardingPr()");
	logger.trace({ config });
	const onboardingBranch = getInheritedOrGlobal("onboardingBranch");
	const existingPr = await platform.getBranchPr(onboardingBranch, config.defaultBranch);
	if (existingPr) {
		if (await ensureOnboardingAutoCloseAge(existingPr)) throw new Error(REPOSITORY_CLOSED_ONBOARDING);
		if (await isOnboardingBranchConflicted(config.defaultBranch, onboardingBranch)) {
			if (GlobalConfig.get("dryRun")) {
				logger.info("DRY-RUN: Would comment that Onboarding PR is conflicted and needs manual resolving");
				return;
			}
			await ensureComment({
				number: existingPr.number,
				topic: "Branch Conflicted",
				content: emojify(`:warning: This PR has a merge conflict which Renovate is unable to automatically resolve, so updates to this PR description are now paused. Please resolve the merge conflict manually.\n\n`)
			});
			return;
		}
	}
	if (OnboardingState.onboardingCacheValid) return;
	const onboardingConfigHashComment = await getOnboardingConfigHashComment();
	const rebaseCheckBox = getRebaseCheckbox(config.onboardingRebaseCheckbox);
	logger.debug("Filling in onboarding PR template");
	let prTemplate = `Welcome to [Renovate](${config.productLinks.homepage})! This is an onboarding PR to help you understand and configure settings before regular Pull Requests begin.\n\n`;
	prTemplate += getInheritedOrGlobal("requireConfig") === "required" ? emojify(`:vertical_traffic_light: To activate Renovate, merge this Pull Request. To disable Renovate, simply close this Pull Request unmerged.\n\n`) : emojify(`:vertical_traffic_light: Renovate will begin keeping your dependencies up-to-date only once you merge or close this Pull Request.\n\n`);
	prTemplate += emojify(`:books: See our [Reading List](https://docs.renovatebot.com/reading-list/) for relevant documentation you may be interested in reading.\n\n`);
	const configFile = getDefaultConfigFileName();
	prTemplate += emojify(`:abcd: Do you want to change how Renovate upgrades your dependencies?`);
	prTemplate += ` Add your custom config to \`${configFile}\` in this branch${config.onboardingRebaseCheckbox ? " and select the Retry/Rebase checkbox below" : ""}. Renovate will update the Pull Request description the next time it runs.`;
	prTemplate += "\n\n";
	prTemplate += emojify(`

---
{{PACKAGE FILES}}
{{CONFIG}}
{{BASEBRANCH}}
{{PRLIST}}
{{WARNINGS}}
{{ERRORS}}

---

:question: Got questions? Check out Renovate's [Docs](${config.productLinks.documentation}), particularly the Getting Started section.
If you need any further assistance then you can also [request help here](${config.productLinks.help}).
`);
	prTemplate += rebaseCheckBox;
	let prBody = prTemplate;
	if (packageFiles && Object.entries(packageFiles).length) {
		let files = [];
		for (const [manager, managerFiles] of Object.entries(packageFiles)) files = files.concat(managerFiles.map((file) => ` * \`${file.packageFile}\` (${manager})`));
		prBody = prBody.replace("{{PACKAGE FILES}}", "### Detected Package Files\n\n" + files.join("\n")) + "\n";
	} else prBody = prBody.replace("{{PACKAGE FILES}}\n", "");
	let configDesc = "";
	if (GlobalConfig.get("dryRun")) logger.info(`DRY-RUN: Would check branch ${onboardingBranch}`);
	else configDesc = getConfigDesc(config, packageFiles);
	prBody = prBody.replace("{{CONFIG}}\n", configDesc);
	prBody = prBody.replace("{{WARNINGS}}\n", getWarnings(config) + getDepWarningsOnboardingPR(packageFiles, config));
	prBody = prBody.replace("{{ERRORS}}\n", getErrors(config));
	prBody = prBody.replace("{{BASEBRANCH}}\n", getBaseBranchDesc(config));
	prBody = prBody.replace("{{PRLIST}}\n", getExpectedPrList(config, branches));
	if (isString(config.prHeader)) prBody = `${compile(config.prHeader, config)}\n\n${prBody}`;
	if (isString(config.prFooter)) prBody = `${prBody}\n---\n\n${compile(config.prFooter, config)}\n`;
	prBody += onboardingConfigHashComment;
	logger.trace("prBody:\n" + prBody);
	prBody = platform.massageMarkdown(prBody, config.rebaseLabel);
	if (existingPr) {
		logger.debug("Found open onboarding PR");
		const prBodyHash = hashBody(prBody);
		if (existingPr.bodyStruct?.hash === prBodyHash) {
			logger.debug(`Pull Request #${existingPr.number} does not need updating`);
			return;
		}
		if (GlobalConfig.get("dryRun")) logger.info("DRY-RUN: Would update onboarding PR");
		else {
			await platform.updatePr({
				number: existingPr.number,
				prTitle: existingPr.title,
				prBody
			});
			logger.info({ pr: existingPr.number }, "Onboarding PR updated");
		}
		return;
	}
	logger.debug("Creating onboarding PR");
	const labels = prepareLabels(config);
	try {
		if (GlobalConfig.get("dryRun")) logger.info("DRY-RUN: Would create onboarding PR");
		else {
			const prTitle = config.semanticCommits === "enabled" ? getSemanticCommitPrTitle(config) : getInheritedOrGlobal("onboardingPrTitle");
			const pr = await platform.createPr({
				sourceBranch: onboardingBranch,
				targetBranch: config.defaultBranch,
				prTitle,
				prBody,
				labels,
				platformPrOptions: getPlatformPrOptions({
					...config,
					automerge: false
				})
			});
			logger.info({ pr: `Pull Request #${pr.number}` }, "Onboarding PR created");
			await addParticipants(config, pr);
		}
	} catch (err) {
		if (err.response?.statusCode === 422 && err.response?.body?.errors?.[0]?.message?.startsWith("A pull request already exists")) {
			logger.warn("Onboarding PR already exists but cannot find it. It was probably created by a different user.");
			await scm.deleteBranch(onboardingBranch);
			return;
		}
		throw err;
	}
}
function getRebaseCheckbox(onboardingRebaseCheckbox) {
	let rebaseCheckBox = "";
	if (onboardingRebaseCheckbox) rebaseCheckBox = `\n\n---\n\n - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, click this checkbox.\n`;
	return rebaseCheckBox;
}
async function getOnboardingConfigHashComment() {
	return `\n<!--renovate-config-hash:${toSha256(await getFile(getDefaultConfigFileName(), getInheritedOrGlobal("onboardingBranch")) ?? "")}-->\n`;
}
//#endregion
export { ensureOnboardingPr };

//# sourceMappingURL=index.js.map