// App-wide transient notifications (toasts).
//
// A single client-side store; the <Toaster /> in the root layout renders it.
// Mutated only from the browser (event handlers / catch blocks), so the
// module-level singleton can't leak across SSR requests — SSR renders an
// empty list and the client takes over after hydration.

export type ToastKind = 'info' | 'success' | 'error';
export type Toast = { id: number; kind: ToastKind; message: string };

const DEFAULT_TIMEOUT_MS = 5000;
// Errors linger longer — the user may need to read what failed.
const ERROR_TIMEOUT_MS = 8000;

class ToastStore {
    toasts = $state<Toast[]>([]);
    private nextId = 1;
    private timers = new Map<number, ReturnType<typeof setTimeout>>();

    /**
     * Queue a toast. `timeoutMs = 0` makes it sticky (dismiss only via the
     * close button / `dismiss`). Returns the id so callers can dismiss early.
     */
    show(message: string, kind: ToastKind = 'info', timeoutMs: number = DEFAULT_TIMEOUT_MS): number {
        const id = this.nextId++;
        this.toasts = [...this.toasts, { id, kind, message }];
        if (timeoutMs > 0) {
            this.timers.set(
                id,
                setTimeout(() => this.dismiss(id), timeoutMs)
            );
        }
        return id;
    }

    error(message: string, timeoutMs: number = ERROR_TIMEOUT_MS): number {
        return this.show(message, 'error', timeoutMs);
    }

    success(message: string, timeoutMs: number = DEFAULT_TIMEOUT_MS): number {
        return this.show(message, 'success', timeoutMs);
    }

    info(message: string, timeoutMs: number = DEFAULT_TIMEOUT_MS): number {
        return this.show(message, 'info', timeoutMs);
    }

    dismiss(id: number): void {
        const timer = this.timers.get(id);
        if (timer) {
            clearTimeout(timer);
            this.timers.delete(id);
        }
        this.toasts = this.toasts.filter((t) => t.id !== id);
    }

    clear(): void {
        this.timers.forEach((t) => clearTimeout(t));
        this.timers.clear();
        this.toasts = [];
    }
}

export const toast = new ToastStore();
