export const SEARCH_RESULTS_SORT = Object.freeze({
	RELEVANCE: "relevance",
	DATE_DESC: "date_desc",
	BRANCH_ASC: "branch_asc",
});

function pad2(value) {
	return String(value || "").padStart(2, "0");
}

/**
 * Extract a comparable branch number from ids like "NL01", "NL200".
 *
 * Why this exists:
 * - A lexicographic compare would sort "NL10" before "NL2" (wrong).
 * - We want deterministic ordering that matches how humans read branch ids.
 *
 * @param {any} branchId
 * @returns {number|null}
 */
function toBranchNumber(branchId) {
	const raw = String(branchId || "").trim();
	const match = /^NL(\d+)$/i.exec(raw);
	if (!match) return null;

	const n = Number(match[1]);
	return Number.isInteger(n) ? n : null;
}

/**
 * Compare two branch ids.
 *
 * Policy:
 * - If both look like NL<number>, compare numerically (NL2 < NL10).
 * - If only one looks like NL<number>, prefer the valid one first.
 * - Otherwise fall back to a stable lexicographic compare.
 *
 * @param {any} a
 * @param {any} b
 * @returns {number}
 */
function compareBranchIds(a, b) {
	const aa = String(a || "");
	const bb = String(b || "");

	const na = toBranchNumber(aa);
	const nb = toBranchNumber(bb);

	if (na !== null && nb !== null) return na - nb;
	if (na !== null && nb === null) return -1;
	if (na === null && nb !== null) return 1;

	return aa.localeCompare(bb, "en");
}

/**
 * Build an ISO-like date key (YYYY-MM-DD) from a search item.
 *
 * Note:
 * - The backend guarantees year/month/day for search items.
 * - We still keep this defensive to avoid runtime crashes on malformed items.
 *
 * @param {any} item
 * @returns {string}
 */
export function toSearchItemIsoDateKey(item) {
	const y = String(item?.year || "");
	const m = pad2(item?.month);
	const d = pad2(item?.day);
	return `${y}-${m}-${d}`;
}

/**
 * Format the search item date as German UI string: DD.MM.YYYY
 *
 * Important:
 * - This is user-facing output (German).
 * - We still keep it pure/testable and independent from UI frameworks.
 *
 * @param {any} item
 * @returns {string}
 */
export function formatSearchItemDateDe(item) {
	const y = String(item?.year || "");
	const m = pad2(item?.month);
	const d = pad2(item?.day);
	return `${d}.${m}.${y}`;
}

/**
 * Sort search items according to the selected sort mode.
 *
 * UX/API policy:
 * - RELEVANCE:
 *   Keep backend order (assumed relevance-ranked). We still return a shallow copy
 *   to avoid accidental mutations by callers.
 *
 * - DATE_DESC:
 *   Newest date first.
 *   Tie-breakers: branch (stable, numeric for NLxx), then filename asc.
 *
 * - BRANCH_ASC:
 *   Branch ascending (NL01..NLxx), then newest date first, then filename asc.
 *   This keeps multi/all searches easy to scan without introducing UI grouping headers.
 *
 * @param {any[]} items
 * @param {"relevance"|"date_desc"|"branch_asc"|string} sortMode
 * @returns {any[]}
 */
export function sortSearchItems(items, sortMode) {
	const arr = Array.isArray(items) ? [...items] : [];

	if (sortMode === SEARCH_RESULTS_SORT.RELEVANCE) return arr;

	if (sortMode === SEARCH_RESULTS_SORT.DATE_DESC) {
		return arr.sort((a, b) => {
			const da = toSearchItemIsoDateKey(a);
			const db = toSearchItemIsoDateKey(b);

			// Newest first
			if (da !== db) return da < db ? 1 : -1;

			// Stable tie-breakers
			const ba = a?.branch;
			const bb = b?.branch;
			const branchCmp = compareBranchIds(ba, bb);
			if (branchCmp !== 0) return branchCmp;

			const fa = String(a?.filename || "");
			const fb = String(b?.filename || "");
			return fa.localeCompare(fb, "de");
		});
	}

	if (sortMode === SEARCH_RESULTS_SORT.BRANCH_ASC) {
		return arr.sort((a, b) => {
			const ba = a?.branch;
			const bb = b?.branch;

			const branchCmp = compareBranchIds(ba, bb);
			if (branchCmp !== 0) return branchCmp;

			// Within the same branch: newest date first
			const da = toSearchItemIsoDateKey(a);
			const db = toSearchItemIsoDateKey(b);
			if (da !== db) return da < db ? 1 : -1;

			const fa = String(a?.filename || "");
			const fb = String(b?.filename || "");
			return fa.localeCompare(fb, "de");
		});
	}

	// Unknown sort mode => fail-safe to backend order.
	return arr;
}
