import { type NotificationItem, parseNotificationEvent } from '$lib/notification/notifications'; export type { NotificationItem }; let notifications = $state([]); let unreadCount = $state(0); let eventSource: EventSource | null = null; let refCount = 0; let errorCount = 0; let navigate: (url: string) => void = (url) => { window.location.href = url; }; async function fetchNotifications(): Promise { try { const res = await fetch('/api/notifications?size=10'); if (res.ok) { const data = await res.json(); notifications = data.content ?? []; } } catch (e) { console.error('Failed to fetch notifications', e); } } async function fetchUnreadCount(): Promise { try { const res = await fetch('/api/notifications/unread-count'); if (res.ok) { const data = await res.json(); unreadCount = data.count; } } catch (e) { console.error('Failed to fetch unread count', e); } } async function markRead(notification: NotificationItem): Promise { if (!notification.read) { try { await fetch(`/api/notifications/${notification.id}/read`, { method: 'PATCH' }); notification.read = true; unreadCount = Math.max(0, unreadCount - 1); } catch (e) { console.error('Failed to mark notification as read', e); } } } async function markAllRead(): Promise { try { await fetch('/api/notifications/read-all', { method: 'POST' }); for (const n of notifications) { n.read = true; } unreadCount = 0; } catch (e) { console.error('Failed to mark all notifications as read', e); } } function init(): void { refCount += 1; if (refCount > 1) return; fetchUnreadCount(); eventSource = new EventSource('/api/notifications/stream'); eventSource.addEventListener('notification', (e) => { const notification = parseNotificationEvent((e as MessageEvent).data); if (!notification) return; notifications = [notification, ...notifications]; if (!notification.read) unreadCount += 1; }); eventSource.onopen = () => { fetchUnreadCount(); errorCount = 0; }; eventSource.onerror = async () => { if (eventSource?.readyState === EventSource.CLOSED) { const res = await fetch('/api/notifications/unread-count'); if (res.status === 401) navigate('/login'); return; } errorCount += 1; if (errorCount >= 3) { eventSource?.close(); eventSource = null; errorCount = 0; const res = await fetch('/api/notifications/unread-count'); if (res.status === 401) navigate('/login'); } }; } function destroy(): void { if (refCount === 0) return; refCount -= 1; if (refCount === 0) { eventSource?.close(); eventSource = null; } } export function __resetForTest(): void { eventSource?.close(); eventSource = null; refCount = 0; errorCount = 0; notifications = []; unreadCount = 0; } export function __setNavigateForTest(fn: (url: string) => void): void { navigate = fn; } export const notificationStore = { get notifications() { return notifications; }, get unreadCount() { return unreadCount; }, fetchNotifications, fetchUnreadCount, markRead, markAllRead, init, destroy };