export type SnackType = 'success' | 'error' | 'info' | 'warning';

export interface Snack {
	id: number;
	type: SnackType;
	message: string;
	detail?: string;
	timeout: number;
}

const DEFAULT_TIMEOUTS: Record<SnackType, number> = {
	success: 3000,
	info: 3000,
	warning: 4000,
	error: 5000,
};

const MAX_VISIBLE = 3;

let nextId = 1;
let snacks = $state<Snack[]>([]);
const timers = new Map<number, ReturnType<typeof setTimeout>>();

export function getSnacks(): Snack[] {
	return snacks;
}

export function addSnack(
	type: SnackType,
	message: string,
	options?: { detail?: string; timeout?: number },
): void {
	const id = nextId++;
	const timeout = options?.timeout ?? DEFAULT_TIMEOUTS[type];
	const snack: Snack = { id, type, message, detail: options?.detail, timeout };

	snacks = [snack, ...snacks];

	// Enforce max visible — single batch removal
	if (snacks.length > MAX_VISIBLE) {
		const overflow = snacks.slice(MAX_VISIBLE);
		for (const s of overflow) {
			const timer = timers.get(s.id);
			if (timer) {
				clearTimeout(timer);
				timers.delete(s.id);
			}
		}
		snacks = snacks.slice(0, MAX_VISIBLE);
	}

	// Auto-dismiss
	if (timeout > 0) {
		timers.set(
			id,
			setTimeout(() => removeSnack(id), timeout),
		);
	}
}

export function removeSnack(id: number): void {
	const timer = timers.get(id);
	if (timer) {
		clearTimeout(timer);
		timers.delete(id);
	}
	snacks = snacks.filter((s) => s.id !== id);
}

// Convenience functions
export function snackSuccess(message: string): void {
	addSnack('success', message);
}

export function snackError(message: string, detail?: string): void {
	addSnack('error', message, { detail });
}

export function snackInfo(message: string): void {
	addSnack('info', message);
}

export function snackWarning(message: string): void {
	addSnack('warning', message);
}
