/** @license MIT | @cube-dev/ui-kit v0.0.0-canary-1fc5ad1 | Cube Dev Team */
import { useEvent } from "../../../_internal/hooks/use-event.js";
import { useRef, useState } from "react";

//#region src/components/overlays/Notifications/use-notification-state.ts
const DEFAULT_NOTIFICATION_DURATION = 3e3;
const DEFAULT_PERSISTENT_NOTIFICATION_DURATION = 5e3;
const MAX_NOTIFICATIONS = 5;
function getDuration(notif) {
	if (notif.duration === null) return null;
	if (notif.duration !== void 0) return notif.duration;
	return notif.persistent ? DEFAULT_PERSISTENT_NOTIFICATION_DURATION : DEFAULT_NOTIFICATION_DURATION;
}
function matchesNotificationId(item, id) {
	return item.id === id || item.internalId === String(id);
}
function findNotification(list, id) {
	return list.find((n) => matchesNotificationId(n, id));
}
/**
* @param timersRef - Ref to the shared OverlayTimers instance. Accessed only
*   inside callbacks (never during render), so it is guaranteed to be populated.
*/
function useNotificationState(timersRef, persistent) {
	const [notifications, setNotifications] = useState([]);
	const notificationsRef = useRef(notifications);
	notificationsRef.current = notifications;
	const idCounter = useRef(0);
	/**
	* Evict the oldest active notification to make room for a new one.
	* Clears its timer and moves it to the persistent list if applicable.
	* Must be called OUTSIDE setState updaters (StrictMode-safe).
	*/
	const evictOldest = useEvent(() => {
		const active = notificationsRef.current.filter((n) => !n.isExiting);
		if (active.length === 0) return null;
		const oldest = active[0];
		timersRef.current?.clearNotificationTimer(oldest.internalId);
		if (oldest.persistent) persistent.addPersistentItem({
			id: oldest.id ?? oldest.internalId,
			theme: oldest.theme,
			title: oldest.title,
			description: oldest.description,
			icon: oldest.icon,
			actions: oldest.actions,
			createdAt: oldest.createdAt,
			updatedAt: oldest.updatedAt,
			isRead: false,
			ownerId: oldest.ownerId
		});
		return oldest.internalId;
	});
	const removeNotification = useEvent((id, reason = "api") => {
		const notif = findNotification(notificationsRef.current, id);
		if (!notif || notif.isExiting) return;
		timersRef.current?.clearNotificationTimer(notif.internalId);
		if (notif.persistent) {
			if (reason === "close" || reason === "timeout") persistent.addPersistentItem({
				id: notif.id ?? notif.internalId,
				theme: notif.theme,
				title: notif.title,
				description: notif.description,
				icon: notif.icon,
				actions: notif.actions,
				createdAt: notif.createdAt,
				updatedAt: notif.updatedAt,
				isRead: true,
				ownerId: notif.ownerId
			});
			else if (reason === "action") persistent.removePersistentItem(notif.id ?? notif.internalId);
		}
		setNotifications((prev) => prev.map((n) => matchesNotificationId(n, id) ? {
			...n,
			isExiting: true
		} : n));
	});
	const finalizeNotificationRemoval = useEvent((internalId) => {
		setNotifications((prev) => prev.filter((n) => n.internalId !== internalId));
	});
	return {
		notifications,
		notificationsRef,
		addNotification: useEvent((options, ownerId) => {
			idCounter.current += 1;
			const internalId = `notif-${idCounter.current}-${Date.now()}`;
			const now = Date.now();
			const id = options.id ?? internalId;
			if (options.id != null && persistent.isFullyDismissedId(options.id)) return id;
			if (options.persistent && options.id != null && persistent.hasDismissedPersistentId(options.id)) {
				persistent.addPersistentItem({
					id,
					theme: options.theme,
					title: options.title,
					description: options.description,
					icon: options.icon,
					actions: options.actions,
					createdAt: now,
					updatedAt: now,
					isRead: false,
					ownerId
				});
				return id;
			}
			const existingNotif = options.id != null ? notificationsRef.current.find((n) => n.id === options.id && !n.isExiting) : void 0;
			if (existingNotif) {
				const returnId = existingNotif.id ?? existingNotif.internalId;
				const prevTitle = existingNotif.title;
				const prevDescription = existingNotif.description;
				const titleChanged = typeof options.title === "string" && typeof prevTitle === "string" && options.title !== prevTitle;
				const descriptionChanged = typeof options.description === "string" && typeof prevDescription === "string" && options.description !== prevDescription;
				if (titleChanged || descriptionChanged) {
					const duration = getDuration(options);
					if (duration != null && duration > 0) timersRef.current?.startNotificationTimer(existingNotif.internalId, existingNotif.id ?? existingNotif.internalId, duration);
				}
				setNotifications((prev) => prev.map((n) => {
					if (n.internalId === existingNotif.internalId) return {
						...n,
						...options,
						internalId: n.internalId,
						createdAt: n.createdAt,
						updatedAt: now,
						ownerId: ownerId ?? n.ownerId
					};
					return n;
				}));
				return returnId;
			}
			const activeCount = notificationsRef.current.filter((n) => !n.isExiting).length;
			const newNotification = {
				...options,
				id,
				internalId,
				createdAt: now,
				updatedAt: now,
				ownerId
			};
			let evictedInternalId = null;
			if (activeCount >= MAX_NOTIFICATIONS) evictedInternalId = evictOldest();
			const duration = getDuration(options);
			if (duration != null && duration > 0) timersRef.current?.startNotificationTimer(internalId, id, duration);
			setNotifications((prev) => {
				let next = prev;
				if (evictedInternalId) next = next.map((n) => n.internalId === evictedInternalId ? {
					...n,
					isExiting: true
				} : n);
				return [...next, newNotification];
			});
			return id;
		}),
		removeNotification,
		updateNotification: useEvent((id, options) => {
			setNotifications((prev) => prev.map((n) => matchesNotificationId(n, id) ? {
				...n,
				...options,
				updatedAt: Date.now()
			} : n));
		}),
		finalizeNotificationRemoval,
		removeByOwner: useEvent((ownerId) => {
			const owned = notificationsRef.current.filter((n) => n.ownerId === ownerId && !n.isExiting);
			for (const n of owned) timersRef.current?.clearNotificationTimer(n.internalId);
			setNotifications((prev) => prev.map((n) => {
				if (n.ownerId === ownerId && !n.isExiting) return {
					...n,
					isExiting: true
				};
				return n;
			}));
		})
	};
}

//#endregion
export { useNotificationState };
//# sourceMappingURL=use-notification-state.js.map