/**
 * Runtime colour theming.
 *
 * The app's colours are Tailwind v4 `@theme` tokens that compile to CSS custom
 * properties (`--color-primary-600` …) which every utility references as
 * `var(...)`. So we can recolour the whole app at runtime by overriding those
 * variables — no rebuild. We derive a full 50→950 ramp for the brand ("primary",
 * which the app authored as `blue-*`) and accent (`purple-*`/`violet-*`/`accent-*`)
 * families from two seed colours, using CSS `color-mix()` so the browser does the
 * tint/shade math.
 *
 * Neutrals (`gray-*`, the pearl→graphite system) are deliberately NOT themed —
 * keeping them fixed guarantees text/background contrast never regresses, and the
 * design language treats greys as the constant that "carries the system".
 *
 * The default (champagne gold) produces an EMPTY override so the hand-tuned ramp in
 * tailwind-theme.css shows through verbatim — zero regression for existing installs.
 */

export type ThemeConfig = { preset: string; primary: string; accent: string };

/** Champagne-gold seed — matches `--color-primary-600` in tailwind-theme.css. */
export const DEFAULT_SEED = '#8a6a2b';

export type Preset = { id: string; label: string; primary: string; accent: string };

/**
 * Curated palettes. The seed is the brand colour at ramp stop 600 (the primary
 * button / FAB), chosen dark enough that white button text clears WCAG AA.
 * MIRROR: the ids are validated server-side in backend/src/handlers/admin.rs
 * (THEME_PRESETS) — add a preset in both places.
 */
export const PRESETS: Preset[] = [
	{ id: 'champagne-gold', label: 'Champagner-Gold', primary: '#8a6a2b', accent: '#8a6a2b' },
	{ id: 'rose', label: 'Rosé', primary: '#9e3f5c', accent: '#9e3f5c' },
	{ id: 'sage', label: 'Salbeigrün', primary: '#4d6a4d', accent: '#4d6a4d' },
	{ id: 'dusk-blue', label: 'Dämmerblau', primary: '#395880', accent: '#395880' },
	{ id: 'classic-silver', label: 'Klassisch Silber', primary: '#5b5b61', accent: '#5b5b61' }
];

/** Resolve a stored theme config to its two effective seed colours. */
export function resolveSeeds(cfg: ThemeConfig): { primary: string; accent: string } {
	if (cfg.preset === 'custom') return { primary: cfg.primary, accent: cfg.accent };
	const p = PRESETS.find((x) => x.id === cfg.preset);
	return p
		? { primary: p.primary, accent: p.accent }
		: { primary: DEFAULT_SEED, accent: DEFAULT_SEED };
}

// stop → color-mix instruction against the seed. 600 is the seed itself; lighter
// stops mix toward white, darker toward black — in oklab for a perceptually even ramp.
const LADDER: Array<[number, string | null]> = [
	[50, 'white 90%'],
	[100, 'white 80%'],
	[200, 'white 62%'],
	[300, 'white 42%'],
	[400, 'white 22%'],
	[500, 'white 9%'],
	[600, null],
	[700, 'black 15%'],
	[800, 'black 30%'],
	[900, 'black 45%'],
	[950, 'black 63%']
];

function stopValue(seed: string, mix: string | null): string {
	return mix ? `color-mix(in oklab, ${seed}, ${mix})` : seed;
}

function ramp(families: string[], seed: string): string {
	let out = '';
	for (const [stop, mix] of LADDER) {
		const val = stopValue(seed, mix);
		for (const fam of families) out += `--color-${fam}-${stop}:${val};`;
	}
	return out;
}

/**
 * Build the `:root:root { … }` override for a theme. `:root:root` (specificity 0,2,0)
 * beats Tailwind's `:root` `@theme` defaults regardless of stylesheet order, so the
 * override wins whether it's injected before (boot) or after the bundle.
 *
 * Returns '' for the default gold, meaning "no override" → the verbatim hand-tuned
 * ramp. Callers treat '' as "remove any injected style".
 */
export function buildPaletteCss(cfg: ThemeConfig): string {
	const { primary, accent } = resolveSeeds(cfg);
	const isDefault = primary.toLowerCase() === DEFAULT_SEED && accent.toLowerCase() === DEFAULT_SEED;
	if (isDefault) return '';

	const accent500 = stopValue(accent, 'white 9%');
	return (
		':root:root{' +
		ramp(['blue', 'primary'], primary) +
		ramp(['purple'], accent) +
		// violet + accent aliases are only used at 500/600 in the app
		`--color-violet-500:${accent500};--color-violet-600:${accent};` +
		`--color-accent-500:${accent500};--color-accent-600:${accent};` +
		'}'
	);
}

const STYLE_ID = 'es-theme';

/** Inject/replace/remove the theme override `<style>`. Empty css removes it. */
export function applyPaletteCss(css: string): void {
	if (typeof document === 'undefined') return;
	let el = document.getElementById(STYLE_ID) as HTMLStyleElement | null;
	if (!css) {
		el?.remove();
		return;
	}
	if (!el) {
		el = document.createElement('style');
		el.id = STYLE_ID;
		document.head.appendChild(el);
	}
	el.textContent = css;
}
