/**
 * Notification Manager
 * Handles toast notifications and user feedback
 */

import { escapeHtml } from './utils.js';
import { renderIcons } from './icons.js';

export class NotificationManager {
    constructor() {
        this.container = null;
        this.notifications = new Map(); // id -> notification element
        this.nextId = 1;
        this.recentNotifications = new Map(); // title+message -> timestamp for deduplication

        // Configuration
        this.config = {
            maxNotifications: 5,
            defaultTimeout: 5000,
            animationDuration: 300,
            position: 'top-right' // top-right, top-left, bottom-right, bottom-left
        };

        // Notification types configuration
        this.typeConfig = {
            success: {
                icon: 'check-circle',
                timeout: 3000,
                class: 'notification--success'
            },
            error: {
                icon: 'alert-circle',
                timeout: 7000,
                class: 'notification--error'
            },
            warning: {
                icon: 'alert-triangle',
                timeout: 5000,
                class: 'notification--warning'
            },
            info: {
                icon: 'info',
                timeout: 4000,
                class: 'notification--info'
            }
        };

        this.init();
    }

    /**
     * Initialize notification system
     */
    init() {
        // Create or find notification container
        this.container = document.getElementById('notifications');

        if (!this.container) {
            this.container = document.createElement('div');
            this.container.id = 'notifications';
            this.container.className = 'notifications';
            document.body.appendChild(this.container);
        }

        console.log('Notification Manager initialized');
    }

    /**
     * Show a notification
     */
    show(options) {
        // Validate options
        if (!options || typeof options !== 'object') {
            console.warn('Invalid notification options:', options);
            return null;
        }

        const { type = 'info', title, message } = options;

        // Don't show notification if both title and message are empty
        if (!title && !message) {
            console.warn('Skipping notification with empty title and message');
            return null;
        }

        // Check for duplicate notifications within the last 2 seconds
        const notificationKey = `${type}:${title}:${message}`;
        const now = Date.now();
        const lastShown = this.recentNotifications.get(notificationKey);

        if (lastShown && (now - lastShown) < 2000) {
            console.log('Skipping duplicate notification:', notificationKey);
            return null; // Skip duplicate notification
        }

        this.recentNotifications.set(notificationKey, now);

        // Clean up old entries (older than 5 seconds)
        for (const [key, timestamp] of this.recentNotifications) {
            if (now - timestamp > 5000) {
                this.recentNotifications.delete(key);
            }
        }

        const notification = this.createNotification(options);
        this.addNotification(notification);
        return notification.id;
    }

    /**
     * Create notification object
     */
    createNotification(options) {
        const {
            type = 'info',
            title,
            message,
            timeout = null,
            persistent = false,
            actions = []
        } = options;

        const id = this.nextId++;
        const config = this.typeConfig[type] || this.typeConfig.info;
        const finalTimeout = persistent ? null : (timeout ?? config.timeout);

        return {
            id,
            type,
            title,
            message,
            timeout: finalTimeout,
            persistent,
            actions,
            config,
            element: null,
            timer: null,
            createdAt: new Date()
        };
    }

    /**
     * Add notification to DOM and manage queue
     */
    addNotification(notification) {
        // Remove oldest notifications if we exceed the limit
        this.enforceMaxNotifications();

        // Create DOM element
        notification.element = this.createNotificationElement(notification);

        // Add to container
        this.container.appendChild(notification.element);

        // Store notification
        this.notifications.set(notification.id, notification);

        // Animate in
        setTimeout(() => {
            notification.element.classList.add('notification--visible');
        }, 10);

        // Set up auto-dismiss timer
        if (notification.timeout) {
            notification.timer = setTimeout(() => {
                this.dismiss(notification.id);
            }, notification.timeout);
        }

        renderIcons(notification.element);

        console.log(` Showing ${notification.type} notification:`, notification.title);
    }

    /**
     * Create notification DOM element
     */
    createNotificationElement(notification) {
        const element = document.createElement('div');
        element.className = `notification ${notification.config.class}`;
        element.dataset.id = notification.id;

        const iconHtml = `<span data-icon="${notification.config.icon}" class="notification__icon"></span>`;

        const titleHtml = notification.title ?
            `<div class="notification__title">${escapeHtml(notification.title)}</div>` : '';

        const messageHtml = notification.message ?
            `<div class="notification__message">${escapeHtml(notification.message)}</div>` : '';

        const actionsHtml = notification.actions.length > 0 ?
            this.createActionsHtml(notification.actions) : '';

        const closeHtml = `
            <button class="notification__close" data-action="close" title="Закрыть">
                <span data-icon="x"></span>
            </button>
        `;

        element.innerHTML = `
            ${iconHtml}
            <div class="notification__content">
                ${titleHtml}
                ${messageHtml}
                ${actionsHtml}
            </div>
            ${closeHtml}
        `;

        // Add event listeners
        this.setupNotificationEvents(element, notification);

        return element;
    }

    /**
     * Create actions HTML for notification
     */
    createActionsHtml(actions) {
        if (actions.length === 0) return '';

        const actionsHtml = actions.map(action => {
            const buttonClass = action.primary ? 'btn btn--primary btn--sm' : 'btn btn--ghost btn--sm';
            return `
                <button class="${buttonClass}" data-action="custom" data-action-id="${action.id}">
                    ${action.icon ? `<span data-icon="${action.icon}"></span>` : ''}
                    ${escapeHtml(action.label)}
                </button>
            `;
        }).join('');

        return `<div class="notification__actions">${actionsHtml}</div>`;
    }

    /**
     * Set up notification event listeners
     */
    setupNotificationEvents(element, notification) {
        element.addEventListener('click', (event) => {
            const action = event.target.closest('[data-action]')?.dataset.action;

            if (action === 'close') {
                this.dismiss(notification.id);
            } else if (action === 'custom') {
                const actionId = event.target.closest('[data-action-id]')?.dataset.actionId;
                const actionConfig = notification.actions.find(a => a.id === actionId);

                if (actionConfig && actionConfig.handler) {
                    try {
                        actionConfig.handler(notification);
                    } catch (error) {
                        console.error('Error in notification action handler:', error);
                    }
                }

                // Auto-dismiss after action unless specified otherwise
                if (!actionConfig || actionConfig.dismissOnClick !== false) {
                    this.dismiss(notification.id);
                }
            }
        });

        // Pause auto-dismiss on hover
        element.addEventListener('mouseenter', () => {
            if (notification.timer) {
                clearTimeout(notification.timer);
                notification.timer = null;
            }
        });

        // Resume auto-dismiss on leave (if not persistent)
        element.addEventListener('mouseleave', () => {
            if (notification.timeout && !notification.persistent && !notification.timer) {
                notification.timer = setTimeout(() => {
                    this.dismiss(notification.id);
                }, 1000); // Shorter timeout after hover
            }
        });
    }

    /**
     * Dismiss notification by ID
     */
    dismiss(id) {
        const notification = this.notifications.get(id);
        if (!notification) return;

        console.log(` Dismissing notification: ${id}`);

        // Clear timer
        if (notification.timer) {
            clearTimeout(notification.timer);
            notification.timer = null;
        }

        // Animate out
        if (notification.element) {
            notification.element.classList.add('notification--dismissing');

            setTimeout(() => {
                if (notification.element && notification.element.parentNode) {
                    notification.element.parentNode.removeChild(notification.element);
                }
                this.notifications.delete(id);
            }, this.config.animationDuration);
        } else {
            this.notifications.delete(id);
        }
    }

    /**
     * Dismiss all notifications
     */
    dismissAll() {
        console.log('Dismissing all notifications');

        for (const id of this.notifications.keys()) {
            this.dismiss(id);
        }
    }

    /**
     * Dismiss notifications by type
     */
    dismissByType(type) {
        console.log(` Dismissing all ${type} notifications`);

        for (const notification of this.notifications.values()) {
            if (notification.type === type) {
                this.dismiss(notification.id);
            }
        }
    }

    /**
     * Update existing notification
     */
    update(id, updates) {
        const notification = this.notifications.get(id);
        if (!notification) return false;

        // Update properties
        Object.assign(notification, updates);

        // Update DOM if needed
        if (updates.title || updates.message) {
            const titleEl = notification.element.querySelector('.notification__title');
            const messageEl = notification.element.querySelector('.notification__message');

            if (titleEl && updates.title !== undefined) {
                titleEl.textContent = updates.title;
            }

            if (messageEl && updates.message !== undefined) {
                messageEl.textContent = updates.message;
            }
        }

        // Update timeout
        if (updates.timeout !== undefined) {
            if (notification.timer) {
                clearTimeout(notification.timer);
            }

            if (updates.timeout > 0) {
                notification.timer = setTimeout(() => {
                    this.dismiss(id);
                }, updates.timeout);
            }
        }

        return true;
    }

    /**
     * Enforce maximum number of notifications
     */
    enforceMaxNotifications() {
        const notifications = Array.from(this.notifications.values())
            .sort((a, b) => a.createdAt - b.createdAt);

        while (notifications.length >= this.config.maxNotifications) {
            const oldest = notifications.shift();
            if (oldest && !oldest.persistent) {
                this.dismiss(oldest.id);
            }
        }
    }

    /**
     * Convenience methods for different notification types
     */
    success(title, message, options = {}) {
        return this.show({
            type: 'success',
            title,
            message,
            ...options
        });
    }

    error(title, message, options = {}) {
        return this.show({
            type: 'error',
            title,
            message,
            ...options
        });
    }

    warning(title, message, options = {}) {
        return this.show({
            type: 'warning',
            title,
            message,
            ...options
        });
    }

    info(title, message, options = {}) {
        return this.show({
            type: 'info',
            title,
            message,
            ...options
        });
    }

    /**
     * Get notification statistics
     */
    getStats() {
        return {
            total: this.notifications.size,
            byType: this.getNotificationsByType(),
            oldestTimestamp: this.getOldestNotificationTime(),
            newestTimestamp: this.getNewestNotificationTime()
        };
    }

    /**
     * Get notifications grouped by type
     */
    getNotificationsByType() {
        const byType = {};

        for (const notification of this.notifications.values()) {
            byType[notification.type] = (byType[notification.type] || 0) + 1;
        }

        return byType;
    }

    /**
     * Get oldest notification timestamp
     */
    getOldestNotificationTime() {
        const notifications = Array.from(this.notifications.values());
        if (notifications.length === 0) return null;

        return Math.min(...notifications.map(n => n.createdAt.getTime()));
    }

    /**
     * Get newest notification timestamp
     */
    getNewestNotificationTime() {
        const notifications = Array.from(this.notifications.values());
        if (notifications.length === 0) return null;

        return Math.max(...notifications.map(n => n.createdAt.getTime()));
    }

    /**
     * Cleanup
     */
    destroy() {
        console.log('Cleaning up Notification Manager...');

        this.dismissAll();

        if (this.container && this.container.parentNode) {
            this.container.parentNode.removeChild(this.container);
        }

        console.log('Notification Manager cleanup complete');
    }
}
