/**
 * Detect the user's preferred app language from an Accept-Language header
 * (or navigator.languages array) — Fase 10.8.
 *
 * Supported app languages (in sync with messages/{en,es}.json + Paraglide
 * languageTags): `en`, `es`. Anything else falls back to `en`.
 *
 * Rules (per plan §10.8.1):
 *   * Inputs we accept:
 *     - bare tag: `'es'`, `'en'`, `'es-ES'`, `'en-US'`
 *     - RFC 7231 list: `'es;q=0.9,en;q=0.8'`
 *     - `navigator.languages` array: `['es-ES', 'en-GB']`
 *     - null / undefined / empty → `'en'`
 *   * If the highest q-scored entry whose primary subtag is `es` has
 *     q ≥ 0.5, the result is `'es'`. Otherwise (including unknown
 *     languages, malformed input, or no clear preference) → `'en'`.
 */
export type AppLanguage = 'en' | 'es';

interface ParsedTag {
	tag: string;
	primary: string;
	q: number;
}

function parseTags(raw: string): ParsedTag[] {
	return raw
		.split(',')
		.map((part) => {
			const segments = part.trim().split(';').map((s) => s.trim());
			if (!segments[0]) return null;
			const tag = segments[0].toLowerCase();
			let q = 1.0;
			for (const seg of segments.slice(1)) {
				const match = seg.match(/^q\s*=\s*([0-9.]+)$/);
				if (match) {
					const parsed = parseFloat(match[1]);
					if (!Number.isNaN(parsed)) q = parsed;
				}
			}
			const primary = tag.split('-')[0];
			// Filter junk: primary must be alpha-only and 1+ chars.
			if (!/^[a-z]+$/.test(primary)) return null;
			return { tag, primary, q };
		})
		.filter((p): p is ParsedTag => p !== null);
}

export function detectLanguage(
	input: string | string[] | null | undefined
): AppLanguage {
	if (input == null) return 'en';

	let parsed: ParsedTag[];

	if (Array.isArray(input)) {
		// navigator.languages: ordered by user preference, no q-scores.
		parsed = input
			.map((tag, index) => {
				const t = tag.toLowerCase().trim();
				if (!t) return null;
				const primary = t.split('-')[0];
				if (!/^[a-z]+$/.test(primary)) return null;
				// Synthesize a decreasing q-score so first-listed wins.
				return { tag: t, primary, q: 1 - index * 0.01 };
			})
			.filter((p): p is ParsedTag => p !== null);
	} else {
		const s = input.trim();
		if (!s) return 'en';
		parsed = parseTags(s);
	}

	if (parsed.length === 0) return 'en';

	// Sort by q-score descending.
	parsed.sort((a, b) => b.q - a.q);

	// First app-known primary wins; if it's es with q ≥ 0.5 → es.
	for (const p of parsed) {
		if (p.primary === 'es') {
			return p.q >= 0.5 ? 'es' : 'en';
		}
		if (p.primary === 'en') return 'en';
	}

	return 'en';
}
