// #region ToastsModule [C:3] [TYPE Module] [SEMANTICS toast, notification, store, dedup, feedback]
// @BRIEF Manages toast notifications using Svelte 5 runes ($state) with deduplication and auto-removal.
// @RELATION BINDS_TO -> [ApiModule]
// @RATIONALE Migrated from Svelte 4 writable store to Svelte 5 $state runes.
//            Keeps .subscribe() for backward compat with $toasts template syntax in Toast.svelte.
//            Explicit _notify() instead of $effect to avoid effect_orphan error in test contexts.

export interface Toast {
	id: string;
	message: string;
	type: 'info' | 'success' | 'error' | 'warning';
	persistent: boolean;
}

let _toasts = $state<Toast[]>([]);
const _subs = new Set<(v: Toast[]) => void>();

function _notify(): void {
	const snapshot = _toasts;
	_subs.forEach(fn => fn(snapshot));
}

export const toasts = {
	subscribe(fn: (v: Toast[]) => void) {
		fn(_toasts);
		_subs.add(fn);
		return () => { _subs.delete(fn); };
	},
};

const TOAST_DEDUP_WINDOW_MS = 1200;
const recentToastByKey = new Map<string, number>();

function buildToastKey(message: string, type: string): string {
	return `${String(type || 'info')}::${String(message || '')}`;
}

function shouldSkipDuplicateToast(message: string, type: string): boolean {
	const key = buildToastKey(message, type);
	const now = Date.now();
	const previousAt = recentToastByKey.get(key);
	if (previousAt && now - previousAt < TOAST_DEDUP_WINDOW_MS) {
		return true;
	}
	recentToastByKey.set(key, now);
	return false;
}

// #region addToast:Function [TYPE Function]
// @PURPOSE: Adds a new toast message.
// @PRE: message string is provided.
// @POST: New toast is added to the store and scheduled for removal.
// @PARAM: message (string) - The message text.
// @PARAM: type (string) - The type of toast (info, success, error, warning).
// @PARAM: duration (number) - Duration in ms before the toast is removed. 0 = persistent (must be dismissed manually).
export function addToast(message: string, type: Toast['type'] = 'info', duration: number = 3000): void {
	if (shouldSkipDuplicateToast(message, type)) {
		console.log(`[toasts.addToast][Action] Duplicate skipped context={{'type': '${type}', 'message': '${message}'}}`);
		return;
	}
	const id = Math.random().toString(36).substr(2, 9);
	const persistent = duration === 0;
	console.log(`[toasts.addToast][Action] Adding toast context={{'id': '${id}', 'type': '${type}', 'message': '${message}', 'persistent': '${persistent}'}}`);
	_toasts = [..._toasts, { id, message, type, persistent }];
	_notify();
	if (!persistent) {
		setTimeout(() => removeToast(id), duration);
	}
}
// #endregion addToast:Function

// #region removeToast:Function [TYPE Function]
// @PURPOSE: Removes a toast message by ID.
// @PRE: id is provided.
// @POST: Toast is removed from the store.
// @PARAM: id (string) - The ID of the toast to remove.
export function removeToast(id: string): void {
	console.log(`[toasts.removeToast][Action] Removing toast context={{'id': '${id}'}}`);
	_toasts = _toasts.filter(t => t.id !== id);
	_notify();
}
// #endregion removeToast:Function
// #endregion ToastsModule
