const ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;

export function isValidIsoDateYmd(value) {
	if (typeof value !== "string") return false;
	const s = value.trim();

	if (!ISO_DATE_RE.test(s)) return false;

	const [y, m, d] = s.split("-").map((x) => Number(x));

	if (!Number.isInteger(y) || !Number.isInteger(m) || !Number.isInteger(d)) {
		return false;
	}

	// Predictable policy (same as backend):
	// - month: 1..12
	// - day: 1..31
	if (m < 1 || m > 12) return false;
	if (d < 1 || d > 31) return false;

	return true;
}

export function normalizeIsoDateYmdOrNull(value) {
	if (typeof value !== "string") return null;

	const s = value.trim();
	if (!s) return null;

	return isValidIsoDateYmd(s) ? s : null;
}

/**
 * Compare ISO dates (YYYY-MM-DD).
 * Lexicographic compare is correct for this format.
 */
export function compareIsoDatesYmd(a, b) {
	const aa = String(a || "");
	const bb = String(b || "");

	if (aa === bb) return 0;
	return aa < bb ? -1 : 1;
}

/**
 * Returns true when both dates exist and the range is invalid (from > to).
 * IMPORTANT: from === to is valid and represents a single day.
 */
export function isInvalidIsoDateRange(from, to) {
	const f = normalizeIsoDateYmdOrNull(from);
	const t = normalizeIsoDateYmdOrNull(to);

	if (!f || !t) return false;
	return f > t;
}

/**
 * Format ISO date (YYYY-MM-DD) as German UI date: DD.MM.YYYY
 */
export function formatIsoDateDe(ymd) {
	const s = normalizeIsoDateYmdOrNull(ymd);
	if (!s) return null;

	const [y, m, d] = s.split("-");
	return `${d}.${m}.${y}`;
}

/**
 * Build a compact German label for the active date filter.
 */
export function formatIsoDateRangeLabelDe({ from = null, to = null } = {}) {
	const f = formatIsoDateDe(from);
	const t = formatIsoDateDe(to);

	if (f && t) {
		if (normalizeIsoDateYmdOrNull(from) === normalizeIsoDateYmdOrNull(to)) {
			return f;
		}
		return `${f} – ${t}`;
	}

	if (f) return `ab ${f}`;
	if (t) return `bis ${t}`;

	return null;
}

/**
 * Convert a Date to ISO YYYY-MM-DD using LOCAL calendar values
 * (avoids timezone drift from toISOString()).
 */
export function toIsoDateYmdFromDate(date) {
	if (!(date instanceof Date) || Number.isNaN(date.getTime())) return null;

	const y = date.getFullYear();
	const m = String(date.getMonth() + 1).padStart(2, "0");
	const d = String(date.getDate()).padStart(2, "0");

	return `${y}-${m}-${d}`;
}

/**
 * Convert ISO YYYY-MM-DD to a Date (local time).
 */
export function toDateFromIsoDateYmd(ymd) {
	const s = normalizeIsoDateYmdOrNull(ymd);
	if (!s) return null;

	const [y, m, d] = s.split("-").map((x) => Number(x));
	return new Date(y, m - 1, d);
}
