"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.showInfoNotification = exports.showWarningNotification = exports.showErrorNotification = exports.showSuccessNotification = exports.createNotification = exports.NotificationSystem = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const useNotificationWebSocket_js_1 = require("./hooks/useNotificationWebSocket.js");
const useNotificationPersistence_js_1 = require("./hooks/useNotificationPersistence.js");
const useNotificationSound_js_1 = require("./hooks/useNotificationSound.js");
const useNotificationPermissions_js_1 = require("./hooks/useNotificationPermissions.js");
const NotificationContainer_js_1 = require("./components/NotificationContainer.js");
const NotificationCenter_js_1 = require("./components/NotificationCenter.js");
const NotificationSettings_js_1 = require("./components/NotificationSettings.js");
const ToastNotification_js_1 = require("./components/ToastNotification.js");
const BannerNotification_js_1 = require("./components/BannerNotification.js");
const ModalNotification_js_1 = require("./components/ModalNotification.js");
const ProgressNotification_js_1 = require("./components/ProgressNotification.js");
const Button_js_1 = require("../Button.js");
const lucide_react_1 = require("lucide-react");
/**
 * NotificationSystem - Comprehensive Real-time Notification Manager
 *
 * A complete notification system featuring:
 * - Real-time WebSocket notifications
 * - Multiple notification types (toast, banner, modal, progress)
 * - Smart grouping and categorization
 * - Persistence and history management
 * - Sound and browser notifications
 * - Advanced filtering and search
 * - Customizable themes and positions
 * - Bulk actions and management
 * - Priority-based queuing
 * - Auto-dismiss and user preferences
 * - Analytics and engagement tracking
 */
const NotificationSystem = ({ position = 'top-right', theme = 'default', maxNotifications = 5, autoCloseDelay = 5000, enableRealtime = true, enablePersistence = true, enableSound = true, enableBrowserNotifications = true, enableGrouping = true, enableFiltering = true, showNotificationCenter = true, showProgress = true, customComponents = {}, className = '', onNotificationClick, onNotificationAction, onNotificationDismiss, onNotificationGroupAction }) => {
    // State management
    const [notifications, setNotifications] = (0, react_1.useState)([]);
    const [notificationGroups, setNotificationGroups] = (0, react_1.useState)([]);
    const [isNotificationCenterOpen, setIsNotificationCenterOpen] = (0, react_1.useState)(false);
    const [isSettingsOpen, setIsSettingsOpen] = (0, react_1.useState)(false);
    const [activeFilters, setActiveFilters] = (0, react_1.useState)({});
    const [soundEnabled, setSoundEnabled] = (0, react_1.useState)(enableSound);
    const [isMinimized, setIsMinimized] = (0, react_1.useState)(false);
    const [currentProgress, setCurrentProgress] = (0, react_1.useState)({});
    // Refs
    const containerRef = (0, react_1.useRef)(null);
    const queueRef = (0, react_1.useRef)([]);
    const processedIds = (0, react_1.useRef)(new Set());
    // Custom hooks
    const { isConnected, lastMessage, connectionStatus, subscribe, unsubscribe, sendMessage } = (0, useNotificationWebSocket_js_1.useNotificationWebSocket)({
        enabled: enableRealtime,
        reconnectInterval: 3000,
        maxReconnectAttempts: 5
    });
    const { saveNotification, loadNotifications, clearNotifications, getNotificationHistory, markAsRead, markAllAsRead } = (0, useNotificationPersistence_js_1.useNotificationPersistence)(enablePersistence);
    const { playSound, stopSound, setSoundEnabled: updateSoundEnabled } = (0, useNotificationSound_js_1.useNotificationSound)(soundEnabled);
    const { hasPermission, requestPermission, showBrowserNotification } = (0, useNotificationPermissions_js_1.useNotificationPermissions)(enableBrowserNotifications);
    // WebSocket message handling
    (0, react_1.useEffect)(() => {
        if (lastMessage && enableRealtime) {
            try {
                const data = JSON.parse(lastMessage);
                if (data.type === 'notification') {
                    addNotification(data.notification);
                }
                else if (data.type === 'notification_update') {
                    updateNotification(data.id, data.updates);
                }
                else if (data.type === 'notification_progress') {
                    updateProgress(data.id, data.progress);
                }
                else if (data.type === 'bulk_notifications') {
                    data.notifications.forEach((notification) => {
                        addNotification(notification);
                    });
                }
            }
            catch (error) {
                console.warn('Failed to parse WebSocket notification:', error);
            }
        }
    }, [lastMessage, enableRealtime]);
    // Load persisted notifications on mount
    (0, react_1.useEffect)(() => {
        if (enablePersistence) {
            loadNotifications().then(persistedNotifications => {
                if (persistedNotifications?.length) {
                    setNotifications(persistedNotifications);
                }
            });
        }
    }, [enablePersistence, loadNotifications]);
    // Notification management
    const addNotification = (0, react_1.useCallback)((notification) => {
        // Prevent duplicate notifications
        if (processedIds.current.has(notification.id)) {
            return;
        }
        processedIds.current.add(notification.id);
        const enhancedNotification = {
            ...notification,
            timestamp: notification.timestamp || new Date(),
            isRead: false,
            isVisible: true
        };
        setNotifications(prev => {
            const newNotifications = [enhancedNotification, ...prev];
            // Limit max notifications
            if (newNotifications.length > maxNotifications * 2) {
                return newNotifications.slice(0, maxNotifications * 2);
            }
            return newNotifications;
        });
        // Play sound for important notifications
        if (soundEnabled && ['error', 'warning', 'success'].includes(notification.type)) {
            playSound(notification.type);
        }
        // Show browser notification
        if (enableBrowserNotifications && hasPermission && !document.hasFocus()) {
            showBrowserNotification(notification);
        }
        // Save to persistence
        if (enablePersistence) {
            saveNotification(enhancedNotification);
        }
        // Auto-dismiss if specified
        if (notification.autoClose !== false && autoCloseDelay > 0) {
            setTimeout(() => {
                dismissNotification(notification.id);
            }, notification.duration || autoCloseDelay);
        }
        // Send analytics
        sendMessage(JSON.stringify({
            type: 'notification_shown',
            id: notification.id,
            type: notification.type,
            timestamp: new Date().toISOString()
        }));
    }, [
        maxNotifications,
        soundEnabled,
        playSound,
        enableBrowserNotifications,
        hasPermission,
        showBrowserNotification,
        enablePersistence,
        saveNotification,
        autoCloseDelay,
        sendMessage
    ]);
    const updateNotification = (0, react_1.useCallback)((id, updates) => {
        setNotifications(prev => prev.map(notification => notification.id === id
            ? { ...notification, ...updates }
            : notification));
        if (enablePersistence) {
            saveNotification({ id, ...updates });
        }
    }, [enablePersistence, saveNotification]);
    const dismissNotification = (0, react_1.useCallback)((id) => {
        setNotifications(prev => prev.map(notification => notification.id === id
            ? { ...notification, isVisible: false }
            : notification));
        // Remove after animation
        setTimeout(() => {
            setNotifications(prev => prev.filter(n => n.id !== id));
            processedIds.current.delete(id);
        }, 300);
        onNotificationDismiss?.(id);
        // Send analytics
        sendMessage(JSON.stringify({
            type: 'notification_dismissed',
            id,
            timestamp: new Date().toISOString()
        }));
    }, [onNotificationDismiss, sendMessage]);
    const dismissAllNotifications = (0, react_1.useCallback)(() => {
        notifications.forEach(notification => {
            if (notification.isVisible) {
                dismissNotification(notification.id);
            }
        });
    }, [notifications, dismissNotification]);
    const markNotificationAsRead = (0, react_1.useCallback)((id) => {
        updateNotification(id, { isRead: true });
        markAsRead(id);
    }, [updateNotification, markAsRead]);
    const markAllNotificationsAsRead = (0, react_1.useCallback)(() => {
        notifications.forEach(notification => {
            if (!notification.isRead) {
                updateNotification(notification.id, { isRead: true });
            }
        });
        markAllAsRead();
    }, [notifications, updateNotification, markAllAsRead]);
    const updateProgress = (0, react_1.useCallback)((id, progress) => {
        setCurrentProgress(prev => ({
            ...prev,
            [id]: progress
        }));
        updateNotification(id, { progress });
    }, [updateNotification]);
    const handleNotificationClick = (0, react_1.useCallback)((notification) => {
        if (!notification.isRead) {
            markNotificationAsRead(notification.id);
        }
        onNotificationClick?.(notification);
        // Send analytics
        sendMessage(JSON.stringify({
            type: 'notification_clicked',
            id: notification.id,
            timestamp: new Date().toISOString()
        }));
    }, [markNotificationAsRead, onNotificationClick, sendMessage]);
    const handleNotificationAction = (0, react_1.useCallback)((notification, action) => {
        onNotificationAction?.(notification, action);
        // Handle built-in actions
        switch (action.type) {
            case 'dismiss':
                dismissNotification(notification.id);
                break;
            case 'archive':
                updateNotification(notification.id, { archived: true });
                break;
            case 'markRead':
                markNotificationAsRead(notification.id);
                break;
            case 'retry':
                if (action.handler) {
                    action.handler(notification);
                }
                break;
        }
        // Send analytics
        sendMessage(JSON.stringify({
            type: 'notification_action',
            notificationId: notification.id,
            action: action.type,
            timestamp: new Date().toISOString()
        }));
    }, [onNotificationAction, dismissNotification, updateNotification, markNotificationAsRead, sendMessage]);
    // Filtering and grouping
    const filteredNotifications = (0, react_1.useMemo)(() => {
        let filtered = notifications.filter(notification => {
            if (!notification.isVisible)
                return false;
            if (activeFilters.type && !activeFilters.type.includes(notification.type)) {
                return false;
            }
            if (activeFilters.read !== undefined && notification.isRead !== activeFilters.read) {
                return false;
            }
            if (activeFilters.priority && notification.priority !== activeFilters.priority) {
                return false;
            }
            if (activeFilters.source && notification.source !== activeFilters.source) {
                return false;
            }
            if (activeFilters.dateRange) {
                const notificationDate = new Date(notification.timestamp);
                const { start, end } = activeFilters.dateRange;
                if (start && notificationDate < start)
                    return false;
                if (end && notificationDate > end)
                    return false;
            }
            return true;
        });
        // Sort by priority and timestamp
        filtered.sort((a, b) => {
            const priorityOrder = { high: 3, medium: 2, low: 1 };
            const aPriority = priorityOrder[a.priority || 'medium'];
            const bPriority = priorityOrder[b.priority || 'medium'];
            if (aPriority !== bPriority) {
                return bPriority - aPriority;
            }
            return new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime();
        });
        return filtered;
    }, [notifications, activeFilters]);
    const visibleNotifications = (0, react_1.useMemo)(() => {
        return filteredNotifications.slice(0, maxNotifications);
    }, [filteredNotifications, maxNotifications]);
    const unreadCount = (0, react_1.useMemo)(() => {
        return notifications.filter(n => !n.isRead && n.isVisible).length;
    }, [notifications]);
    // Notification grouping
    const groupedNotifications = (0, react_1.useMemo)(() => {
        if (!enableGrouping)
            return null;
        const groups = {};
        filteredNotifications.forEach(notification => {
            const groupKey = notification.group || notification.source || 'general';
            if (!groups[groupKey]) {
                groups[groupKey] = {
                    id: groupKey,
                    title: groupKey.charAt(0).toUpperCase() + groupKey.slice(1),
                    notifications: [],
                    count: 0,
                    unreadCount: 0,
                    lastUpdate: notification.timestamp
                };
            }
            groups[groupKey].notifications.push(notification);
            groups[groupKey].count++;
            if (!notification.isRead) {
                groups[groupKey].unreadCount++;
            }
            if (new Date(notification.timestamp) > new Date(groups[groupKey].lastUpdate)) {
                groups[groupKey].lastUpdate = notification.timestamp;
            }
        });
        return Object.values(groups).sort((a, b) => new Date(b.lastUpdate).getTime() - new Date(a.lastUpdate).getTime());
    }, [filteredNotifications, enableGrouping]);
    // Render notification by type
    const renderNotification = (notification) => {
        const commonProps = {
            notification,
            onClick: () => handleNotificationClick(notification),
            onDismiss: () => dismissNotification(notification.id),
            onAction: (action) => handleNotificationAction(notification, action),
            theme,
            progress: currentProgress[notification.id]
        };
        // Custom component override
        if (customComponents[notification.type]) {
            const CustomComponent = customComponents[notification.type];
            return (0, jsx_runtime_1.jsx)(CustomComponent, { ...commonProps }, notification.id);
        }
        // Built-in notification types
        switch (notification.displayType || 'toast') {
            case 'banner':
                return (0, jsx_runtime_1.jsx)(BannerNotification_js_1.BannerNotification, { ...commonProps }, notification.id);
            case 'modal':
                return (0, jsx_runtime_1.jsx)(ModalNotification_js_1.ModalNotification, { ...commonProps }, notification.id);
            case 'progress':
                return (0, jsx_runtime_1.jsx)(ProgressNotification_js_1.ProgressNotification, { ...commonProps }, notification.id);
            case 'toast':
            default:
                return (0, jsx_runtime_1.jsx)(ToastNotification_js_1.ToastNotification, { ...commonProps }, notification.id);
        }
    };
    return ((0, jsx_runtime_1.jsxs)("div", { className: `notification-system ${theme} ${className}`, children: [(0, jsx_runtime_1.jsx)("div", { className: "notification-toggle", children: (0, jsx_runtime_1.jsxs)(Button_js_1.Button, { variant: "ghost", size: "sm", onClick: () => setIsNotificationCenterOpen(!isNotificationCenterOpen), className: "relative", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Bell, { className: "w-5 h-5" }), unreadCount > 0 && ((0, jsx_runtime_1.jsx)("span", { className: "absolute -top-1 -right-1 bg-red-500 text-white text-xs rounded-full w-5 h-5 flex items-center justify-center", children: unreadCount > 99 ? '99+' : unreadCount }))] }) }), (0, jsx_runtime_1.jsxs)(NotificationContainer_js_1.NotificationContainer, { ref: containerRef, position: position, theme: theme, isMinimized: isMinimized, className: `${isMinimized ? 'minimized' : ''}`, children: [(0, jsx_runtime_1.jsxs)("div", { className: "notification-container-header", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center space-x-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Bell, { className: "w-4 h-4" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-sm font-medium", children: ["Notifications (", visibleNotifications.length, ")"] }), isConnected && ((0, jsx_runtime_1.jsx)("div", { className: "connection-indicator connected", children: (0, jsx_runtime_1.jsx)("div", { className: "w-2 h-2 bg-green-400 rounded-full" }) }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center space-x-1", children: [enableFiltering && ((0, jsx_runtime_1.jsx)(Button_js_1.Button, { variant: "ghost", size: "xs", onClick: () => setIsNotificationCenterOpen(true), children: (0, jsx_runtime_1.jsx)(lucide_react_1.Filter, { className: "w-3 h-3" }) })), (0, jsx_runtime_1.jsx)(Button_js_1.Button, { variant: "ghost", size: "xs", onClick: () => setSoundEnabled(!soundEnabled), children: soundEnabled ? (0, jsx_runtime_1.jsx)(lucide_react_1.Volume2, { className: "w-3 h-3" }) : (0, jsx_runtime_1.jsx)(lucide_react_1.VolumeX, { className: "w-3 h-3" }) }), (0, jsx_runtime_1.jsx)(Button_js_1.Button, { variant: "ghost", size: "xs", onClick: () => setIsMinimized(!isMinimized), children: isMinimized ? (0, jsx_runtime_1.jsx)(lucide_react_1.Maximize, { className: "w-3 h-3" }) : (0, jsx_runtime_1.jsx)(lucide_react_1.Minimize, { className: "w-3 h-3" }) }), (0, jsx_runtime_1.jsx)(Button_js_1.Button, { variant: "ghost", size: "xs", onClick: () => setIsSettingsOpen(true), children: (0, jsx_runtime_1.jsx)(lucide_react_1.Settings, { className: "w-3 h-3" }) })] })] }), visibleNotifications.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { className: "notification-actions", children: [(0, jsx_runtime_1.jsxs)(Button_js_1.Button, { variant: "ghost", size: "xs", onClick: markAllNotificationsAsRead, disabled: visibleNotifications.every(n => n.isRead), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Check, { className: "w-3 h-3 mr-1" }), "Mark All Read"] }), (0, jsx_runtime_1.jsxs)(Button_js_1.Button, { variant: "ghost", size: "xs", onClick: dismissAllNotifications, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.X, { className: "w-3 h-3 mr-1" }), "Dismiss All"] })] }))] }), !isMinimized && ((0, jsx_runtime_1.jsx)("div", { className: "notification-list", children: visibleNotifications.length === 0 ? ((0, jsx_runtime_1.jsxs)("div", { className: "empty-state", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Bell, { className: "w-8 h-8 text-gray-400 mx-auto mb-2" }), (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-gray-500 text-center", children: "No notifications to display" })] })) : ((0, jsx_runtime_1.jsx)("div", { className: "notifications", children: visibleNotifications.map(renderNotification) })) }))] }), showNotificationCenter && isNotificationCenterOpen && ((0, jsx_runtime_1.jsx)(NotificationCenter_js_1.NotificationCenter, { isOpen: isNotificationCenterOpen, onClose: () => setIsNotificationCenterOpen(false), notifications: filteredNotifications, groups: groupedNotifications, activeFilters: activeFilters, onFiltersChange: setActiveFilters, onNotificationClick: handleNotificationClick, onNotificationAction: handleNotificationAction, onGroupAction: onNotificationGroupAction, onMarkAllRead: markAllNotificationsAsRead, onClearAll: dismissAllNotifications, enableGrouping: enableGrouping, enableFiltering: enableFiltering, theme: theme })), isSettingsOpen && ((0, jsx_runtime_1.jsx)(NotificationSettings_js_1.NotificationSettings, { isOpen: isSettingsOpen, onClose: () => setIsSettingsOpen(false), settings: {
                    soundEnabled,
                    position,
                    theme,
                    autoCloseDelay,
                    maxNotifications,
                    enableRealtime,
                    enablePersistence,
                    enableBrowserNotifications
                }, onSettingsChange: (newSettings) => {
                    setSoundEnabled(newSettings.soundEnabled);
                    updateSoundEnabled(newSettings.soundEnabled);
                    // Update other settings...
                }, onRequestPermission: requestPermission, hasPermission: hasPermission })), enableRealtime && !isConnected && ((0, jsx_runtime_1.jsxs)("div", { className: "connection-banner bg-yellow-100 border border-yellow-300 text-yellow-800 px-4 py-2 text-sm", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.AlertTriangle, { className: "w-4 h-4 inline mr-2" }), "Real-time notifications disconnected. Attempting to reconnect...", (0, jsx_runtime_1.jsxs)(Button_js_1.Button, { variant: "ghost", size: "xs", onClick: () => window.location.reload(), className: "ml-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.RefreshCw, { className: "w-3 h-3" }), "Refresh"] })] }))] }));
};
exports.NotificationSystem = NotificationSystem;
// Export utility functions for external use
const createNotification = (type, title, message, options = {}) => ({
    id: `notification_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
    type,
    title,
    message,
    timestamp: new Date(),
    isRead: false,
    isVisible: true,
    ...options
});
exports.createNotification = createNotification;
const showSuccessNotification = (title, message, options) => (0, exports.createNotification)('success', title, message, options);
exports.showSuccessNotification = showSuccessNotification;
const showErrorNotification = (title, message, options) => (0, exports.createNotification)('error', title, message, { autoClose: false, ...options });
exports.showErrorNotification = showErrorNotification;
const showWarningNotification = (title, message, options) => (0, exports.createNotification)('warning', title, message, options);
exports.showWarningNotification = showWarningNotification;
const showInfoNotification = (title, message, options) => (0, exports.createNotification)('info', title, message, options);
exports.showInfoNotification = showInfoNotification;
exports.default = exports.NotificationSystem;
//# sourceMappingURL=NotificationSystem.js.map