import { getEnv } from "../../../util/env.js";
import { regEx } from "../../../util/regex.js";
import { logger } from "../../../logger/index.js";
import { LooseArray, LooseRecord, Toml, withDepType } from "../../../util/schema-utils/index.js";
import { parseGitUrl } from "../../../util/git/url.js";
import { id, isValid } from "../../versioning/pep440/index.js";
import { GitTagsDatasource } from "../../datasource/git-tags/index.js";
import { GithubTagsDatasource } from "../../datasource/github-tags/index.js";
import { normalizePythonDepName } from "../../datasource/pypi/common.js";
import { PypiDatasource } from "../../datasource/pypi/index.js";
import { GitlabTagsDatasource } from "../../datasource/gitlab-tags/index.js";
import { id as id$1 } from "../../versioning/git/index.js";
import { id as id$2, isValid as isValid$1 } from "../../versioning/poetry/index.js";
import { uniq } from "../../../util/uniq.js";
import { GitRefsDatasource } from "../../datasource/git-refs/index.js";
import { depTypes } from "../pep621/utils.js";
import { DependencyGroup, ProjectSection } from "../pep621/schema.js";
import { dependencyPattern } from "../pip_requirements/extract.js";
import { z } from "zod";

//#region lib/modules/manager/poetry/schema.ts
const PoetryOptionalDependencyMixin = z.object({ optional: z.boolean().optional().catch(false) }).transform(({ optional }) => optional ? { depType: "extras" } : {});
const PoetryPathDependency = z.object({
	path: z.string(),
	version: z.string().optional().catch(void 0)
}).transform(({ version }) => {
	const dep = {
		datasource: PypiDatasource.id,
		skipReason: "path-dependency"
	};
	if (version) dep.currentValue = version;
	return dep;
}).and(PoetryOptionalDependencyMixin);
const PoetryGitDependency = z.object({
	git: z.string(),
	tag: z.string().optional().catch(void 0),
	version: z.string().optional().catch(void 0),
	branch: z.string().optional().catch(void 0),
	rev: z.string().optional().catch(void 0)
}).transform(({ git, tag, version, branch, rev }) => {
	if (tag) {
		const { source, owner, name } = parseGitUrl(git);
		const repo = `${owner}/${name}`;
		if (source === "github.com") return {
			datasource: GithubTagsDatasource.id,
			currentValue: tag,
			packageName: repo
		};
		else if (source === "gitlab.com") return {
			datasource: GitlabTagsDatasource.id,
			currentValue: tag,
			packageName: repo
		};
		else return {
			datasource: GitTagsDatasource.id,
			currentValue: tag,
			packageName: git
		};
	}
	if (rev) return {
		datasource: GitRefsDatasource.id,
		currentValue: branch,
		currentDigest: rev,
		replaceString: rev,
		packageName: git
	};
	return {
		datasource: GitRefsDatasource.id,
		currentValue: version,
		packageName: git,
		skipReason: "git-dependency"
	};
}).and(PoetryOptionalDependencyMixin);
const PoetryPypiDependency = z.union([z.object({
	version: z.string().optional(),
	source: z.string().optional()
}).transform(({ version: currentValue, source }) => {
	if (!currentValue) return { datasource: PypiDatasource.id };
	return {
		datasource: PypiDatasource.id,
		managerData: {
			nestedVersion: true,
			...source ? { sourceName: source.toLowerCase() } : {}
		},
		currentValue
	};
}).and(PoetryOptionalDependencyMixin), z.string().transform((version) => ({
	datasource: PypiDatasource.id,
	currentValue: version,
	managerData: { nestedVersion: false }
}))]);
const PoetryArrayDependency = z.array(z.unknown()).transform(() => ({
	datasource: PypiDatasource.id,
	skipReason: "multiple-constraint-dep"
}));
const PoetryDependency = z.union([
	PoetryPathDependency,
	PoetryGitDependency,
	PoetryPypiDependency,
	PoetryArrayDependency
]);
const PoetryDependencies = LooseRecord(z.string(), PoetryDependency.transform((dep) => {
	if (dep.skipReason) return dep;
	if (dep.datasource === GitRefsDatasource.id && dep.currentDigest) {
		dep.versioning = id$1;
		return dep;
	}
	// istanbul ignore if: normaly should not happen
	if (!dep.currentValue) {
		dep.skipReason = "unspecified-version";
		return dep;
	}
	if (isValid(dep.currentValue)) {
		dep.versioning = id;
		return dep;
	}
	if (isValid$1(dep.currentValue)) {
		dep.versioning = id$2;
		return dep;
	}
	dep.skipReason = "invalid-version";
	return dep;
})).transform((record) => {
	const deps = [];
	for (const [depName, dep] of Object.entries(record)) {
		dep.depName = depName;
		if (!dep.packageName) {
			const packageName = normalizePythonDepName(depName);
			if (depName !== packageName) dep.packageName = packageName;
		}
		deps.push(dep);
	}
	return deps;
});
const PoetryGroupDependencies = LooseRecord(z.string(), z.object({ dependencies: PoetryDependencies }).transform(({ dependencies }) => dependencies)).transform((record) => {
	const deps = [];
	for (const [name, val] of Object.entries(record)) for (const dep of Object.values(val)) {
		dep.depType = name;
		deps.push(dep);
	}
	return deps;
});
const PoetrySourceOrder = [
	"default",
	"primary",
	"secondary",
	"supplemental",
	"explicit"
];
const PoetrySource = z.object({
	name: z.string().toLowerCase(),
	url: z.string().optional(),
	priority: z.enum(PoetrySourceOrder).default("primary")
});
const PoetrySources = LooseArray(PoetrySource, { onError: ({ error: err }) => {
	logger.debug({ err }, "Poetry: error parsing sources array");
} }).transform((sources) => {
	const pypiUrl = getEnv().PIP_INDEX_URL ?? "https://pypi.org/pypi/";
	const result = [];
	let overridesPyPi = false;
	let hasDefaultSource = false;
	let hasPrimarySource = false;
	for (const source of sources) {
		if (source.name === "pypi") {
			source.url = pypiUrl;
			overridesPyPi = true;
		}
		if (!source.url) continue;
		if (source.priority === "default") hasDefaultSource = true;
		else if (source.priority === "primary") hasPrimarySource = true;
		result.push(source);
	}
	if (sources.length && !hasDefaultSource && !overridesPyPi) result.push({
		name: "pypi",
		priority: hasPrimarySource ? "secondary" : "default",
		url: pypiUrl
	});
	result.sort((a, b) => PoetrySourceOrder.indexOf(a.priority) - PoetrySourceOrder.indexOf(b.priority));
	return result;
}).catch([]);
const PoetrySection = z.object({
	version: z.string().optional().catch(void 0),
	dependencies: withDepType(PoetryDependencies, "dependencies", false).optional(),
	"dev-dependencies": withDepType(PoetryDependencies, "dev-dependencies").optional(),
	group: PoetryGroupDependencies.optional(),
	source: PoetrySources
});
const BuildSystemRequireVal = z.string().nonempty().transform((val) => regEx(`^${dependencyPattern}$`).exec(val)).transform((match, ctx) => {
	if (!match) {
		ctx.addIssue({
			code: z.ZodIssueCode.custom,
			message: "invalid requirement"
		});
		return z.NEVER;
	}
	const [, depName, , poetryRequirement] = match;
	return {
		depName,
		poetryRequirement
	};
});
const PoetryPyProject = Toml.pipe(z.object({
	project: ProjectSection.optional().catch(void 0),
	tool: z.object({ poetry: PoetrySection }).optional().catch(void 0),
	"dependency-groups": DependencyGroup(depTypes.dependencyGroups).catch([]),
	"build-system": z.object({
		"build-backend": z.string().refine((buildBackend) => buildBackend === "poetry.masonry.api" || buildBackend === "poetry.core.masonry.api"),
		requires: LooseArray(BuildSystemRequireVal).transform((vals) => {
			return vals.find(({ depName }) => depName === "poetry" || depName === "poetry_core" || depName === "poetry-core")?.poetryRequirement;
		})
	}).transform(({ requires: poetryRequirement }) => poetryRequirement).optional().catch(void 0)
}).transform((pyproject) => {
	const { project, tool, "build-system": poetryRequirement, "dependency-groups": dependencyGroups } = pyproject;
	const deps = [];
	const projectDependencies = project?.dependencies;
	if (projectDependencies) deps.push(...projectDependencies);
	const projectOptionalDependencies = project?.["optional-dependencies"];
	if (projectOptionalDependencies) deps.push(...projectOptionalDependencies);
	deps.push(...dependencyGroups);
	const poetryDependencies = tool?.poetry?.dependencies;
	if (poetryDependencies) deps.push(...poetryDependencies);
	const poetryDevDependencies = tool?.poetry?.["dev-dependencies"];
	if (poetryDevDependencies) deps.push(...poetryDevDependencies);
	const poetryGroupDependencies = tool?.poetry?.group;
	if (poetryGroupDependencies) deps.push(...poetryGroupDependencies);
	const packageFileContent = {
		deps,
		packageFileVersion: tool?.poetry?.version
	};
	const sourceUrls = tool?.poetry?.source;
	if (sourceUrls) {
		for (const dep of deps) if (dep.managerData?.sourceName) {
			const sourceUrl = sourceUrls.find(({ name }) => name === dep.managerData?.sourceName);
			if (sourceUrl?.url) dep.registryUrls = [sourceUrl.url];
		}
		const sourceUrlsFiltered = sourceUrls.filter(({ priority }) => priority !== "explicit");
		if (sourceUrlsFiltered.length) packageFileContent.registryUrls = uniq(sourceUrlsFiltered.map(({ url }) => url));
	}
	return {
		packageFileContent,
		poetryRequirement
	};
}));
const poetryConstraint = {
	"1.0": "<1.1.0",
	"1.1": "<1.3.0",
	"2.0": ">=1.3.0 <1.4.0"
};
const Lockfile = Toml.pipe(z.object({
	package: LooseArray(z.object({
		name: z.string(),
		version: z.string()
	}).transform(({ name, version }) => [name, version])).transform((entries) => Object.fromEntries(entries)).catch({}),
	metadata: z.object({
		"lock-version": z.string().transform((lockVersion) => poetryConstraint[lockVersion]).optional().catch(void 0),
		"python-versions": z.string().optional().catch(void 0)
	}).transform(({ "lock-version": poetryConstraint, "python-versions": pythonVersions }) => ({
		poetryConstraint,
		pythonVersions
	})).catch({
		poetryConstraint: void 0,
		pythonVersions: void 0
	})
})).transform(({ package: lock, metadata: { poetryConstraint, pythonVersions } }) => ({
	lock,
	poetryConstraint,
	pythonVersions
}));

//#endregion
export { Lockfile, PoetryPyProject };
//# sourceMappingURL=schema.js.map