import spdxLicenseList from "spdx-license-list/full.js";
//#region src/lib/utilities/license-identification.ts
/**
* License identification using Dice coefficient on bigrams.
*
* Compares plain-text license file content against the full SPDX license list
* to identify the best-matching SPDX license identifier. Returns a standard
* SPDX license URL (e.g. "https://spdx.org/licenses/MIT").
*
* Handles:
*   - Standard license texts (MIT, BSD, Apache, etc.)
*   - GNU family licenses via header pattern matching (LGPL, AGPL)
*   - Markdown-formatted license files (strips headings, tables, links)
*   - YAML front matter stripping
*/
/** Minimum similarity score to consider a match. */
const CONFIDENCE_THRESHOLD = .75;
/**
* Identify the SPDX license that best matches the given text.
* Returns the best match with confidence score, or undefined if no match
* exceeds the confidence threshold.
*/
function identifyLicense(text) {
	const headerMatch = identifyByHeader(text);
	if (headerMatch) return headerMatch;
	const normalizedInput = normalizeInput(text);
	if (normalizedInput.length < 2) return void 0;
	const inputBigramsMap = computeBigrams(normalizedInput);
	const inputTotal = normalizedInput.length - 1;
	let bestMatch;
	let bestScore = 0;
	for (const { bigramsMap, normalized, spdxId, totalBigrams } of getNormalizedLicenses()) {
		if (normalizedInput === normalized) return {
			confidence: 1,
			spdxId
		};
		const score = diceCoefficientCached(inputBigramsMap, inputTotal, bigramsMap, totalBigrams);
		if (score > bestScore) {
			bestScore = score;
			bestMatch = {
				confidence: score,
				spdxId
			};
		}
	}
	if (bestMatch && bestMatch.confidence >= CONFIDENCE_THRESHOLD) return bestMatch;
}
/**
* Strip YAML front matter (--- delimited blocks at the start of a file).
*/
function stripFrontMatter(text) {
	if (text.startsWith("---")) {
		const end = text.indexOf("---", 3);
		if (end !== -1) return text.slice(end + 3);
	}
	return text;
}
/**
* Normalize license text for comparison.
* Follows SPDX matching guidelines: collapse whitespace, strip copyright lines,
* remove URLs, lowercase.
*/
function normalizeText(text) {
	return text.replaceAll(/^#+\s+/gm, "").replaceAll(/^copyright.*$/gim, "").replaceAll(/^\|.*\|$/gm, "").replaceAll(/^[-|:\s]+$/gm, "").replaceAll(/https?:\/\/\S+/g, "").replaceAll(/\S+@\S+/g, "").replaceAll(/[[\]()]/g, " ").replaceAll(/\s+/g, " ").trim().toLowerCase();
}
/**
* Normalize input text (user-provided license file).
* Applies additional cleanup beyond what reference texts need.
*/
function normalizeInput(text) {
	return normalizeText(stripFrontMatter(text));
}
/**
* Compute bigrams (2-character substrings) of a string.
*/
function computeBigrams(text) {
	const map = /* @__PURE__ */ new Map();
	for (let index = 0; index < text.length - 1; index++) {
		const pair = text.slice(index, index + 2);
		map.set(pair, (map.get(pair) ?? 0) + 1);
	}
	return map;
}
let normalizedLicenses;
function getNormalizedLicenses() {
	normalizedLicenses ??= Object.entries(spdxLicenseList).map(([spdxId, entry]) => {
		const normalized = normalizeText(entry.licenseText);
		return {
			bigramsMap: computeBigrams(normalized),
			normalized,
			spdxId,
			totalBigrams: normalized.length - 1
		};
	});
	return normalizedLicenses;
}
/**
* Compute the Dice coefficient using pre-computed bigrams for one side.
*/
function diceCoefficientCached(inputBigrams, inputTotal, referenceBigrams, referenceTotal) {
	let intersection = 0;
	for (const [pair, countA] of inputBigrams) {
		const countB = referenceBigrams.get(pair);
		if (countB !== void 0) intersection += Math.min(countA, countB);
	}
	return 2 * intersection / (inputTotal + referenceTotal);
}
/**
* Title-based identification for GNU licenses whose SPDX templates embed
* combined texts (e.g. LGPL-3.0-only = LGPL supplement + full GPL), making
* Dice coefficient unreliable against real-world standalone files.
* Only checks the first 500 characters to avoid matching references in
* unrelated license texts (e.g. CeCILL-2.1 mentions AGPL in its body).
*/
const HEADER_PATTERNS = [
	{
		pattern: /gnu lesser general public license\s+version 3/i,
		spdxId: "LGPL-3.0-only"
	},
	{
		pattern: /gnu lesser general public license\s+version 2\.1/i,
		spdxId: "LGPL-2.1-only"
	},
	{
		pattern: /gnu lesser general public license\s+version 2(?:\.0)?(?!\.\d)/i,
		spdxId: "LGPL-2.0-only"
	},
	{
		pattern: /gnu affero general public license\s+version 3/i,
		spdxId: "AGPL-3.0-only"
	}
];
function identifyByHeader(text) {
	const header = text.slice(0, 500);
	for (const { pattern, spdxId } of HEADER_PATTERNS) if (pattern.test(header)) return {
		confidence: 1,
		spdxId
	};
}
//#endregion
export { identifyLicense };
