// Notification Manager - Centralized alert and notification dispatch
// Handles browser notifications, content script alerts, and audit logging

export class NotificationManager {
  constructor(config = {}) {
    this.config = config;
    this.notifications = new Map();  // id -> notification_data
    this.listeners = new Set();
    this.notificationHistory = [];
    this.maxHistorySize = 100;
  }

  /**
   * Show notification to user
   * @param {object} notification - Notification data
   * @returns {string} - Notification ID
   */
  async notify(notification) {
    const id = this.generateId();
    const timestamp = Date.now();

    const notificationData = {
      id,
      timestamp,
      type: notification.type || 'warning',      // info, warning, error, critical
      title: notification.title || 'Security Alert',
      message: notification.message,
      details: notification.details || null,
      action: notification.action || 'warn',     // block, warn, allow
      source: notification.source || 'unknown',  // detector name
      url: notification.url || null,
      riskLevel: notification.riskLevel || 'medium',
      dismissed: false
    };

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

    // Trim history
    if (this.notificationHistory.length > this.maxHistorySize) {
      this.notificationHistory.pop();
    }

    // Dispatch based on severity
    switch (notificationData.type) {
      case 'critical':
      case 'error':
        await this.showBrowserNotification(notificationData);
        await this.showContentScriptAlert(notificationData);
        break;

      case 'warning':
        if (this.config.showWarnings !== false) {
          await this.showBrowserNotification(notificationData);
        }
        break;

      case 'info':
        if (this.config.showInfo === true) {
          await this.showBrowserNotification(notificationData);
        }
        break;
    }

    // Notify listeners
    this.notifyListeners('notification-created', notificationData);

    // Auto-dismiss after timeout
    if (this.config.autoDismissTimeout) {
      setTimeout(() => {
        this.dismiss(id);
      }, this.config.autoDismissTimeout);
    }

    return id;
  }

  /**
   * Show browser notification
   * @param {object} notification - Notification data
   */
  async showBrowserNotification(notification) {
    try {
      await chrome.notifications.create(notification.id, {
        type: 'basic',
        iconUrl: chrome.runtime.getURL('icons/icon48.png'),
        title: notification.title,
        message: notification.message,
        priority: notification.type === 'critical' ? 2 : 1
      });
    } catch (error) {
      console.error('[NotificationManager] Failed to show browser notification:', error);
    }
  }

  /**
   * Show alert in content script
   * @param {object} notification - Notification data
   */
  async showContentScriptAlert(notification) {
    try {
      // Send message to content script
      const tabs = await chrome.tabs.query({ active: true, currentWindow: true });
      if (tabs.length > 0) {
        await chrome.tabs.sendMessage(tabs[0].id, {
          type: 'SHOW_ALERT',
          notification
        });
      }
    } catch (error) {
      console.error('[NotificationManager] Failed to show content script alert:', error);
    }
  }

  /**
   * Dismiss notification
   * @param {string} id - Notification ID
   */
  dismiss(id) {
    const notification = this.notifications.get(id);
    if (notification) {
      notification.dismissed = true;
      notification.dismissedAt = Date.now();

      // Clear browser notification
      chrome.notifications.clear(id);

      this.notifyListeners('notification-dismissed', notification);
    }
  }

  /**
   * Get notification by ID
   * @param {string} id - Notification ID
   * @returns {object} - Notification data or null
   */
  get(id) {
    return this.notifications.get(id) || null;
  }

  /**
   * Get all active notifications
   * @returns {array} - Array of active notifications
   */
  getActive() {
    return Array.from(this.notifications.values())
      .filter(n => !n.dismissed)
      .sort((a, b) => b.timestamp - a.timestamp);
  }

  /**
   * Get notification history
   * @param {number} limit - Max number to return
   * @returns {array} - Array of notifications
   */
  getHistory(limit = 50) {
    return this.notificationHistory.slice(0, limit);
  }

  /**
   * Clear all notifications
   */
  clearAll() {
    for (const id of this.notifications.keys()) {
      this.dismiss(id);
    }
    this.notifications.clear();
  }

  /**
   * Generate unique notification ID
   * @returns {string} - Unique ID
   */
  generateId() {
    return `notif_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }

  /**
   * Add listener for notification events
   * @param {function} callback - Callback function (event, data)
   */
  addListener(callback) {
    this.listeners.add(callback);
  }

  /**
   * Remove listener
   * @param {function} callback - Callback function
   */
  removeListener(callback) {
    this.listeners.delete(callback);
  }

  /**
   * Notify all listeners
   * @param {string} event - Event name
   * @param {object} data - Event data
   */
  notifyListeners(event, data) {
    for (const listener of this.listeners) {
      try {
        listener(event, data);
      } catch (error) {
        console.error('[NotificationManager] Listener error:', error);
      }
    }
  }

  /**
   * Get statistics
   * @returns {object} - Stats
   */
  getStats() {
    const active = this.getActive();
    const byType = {};
    const byRisk = {};

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

    return {
      total: this.notificationHistory.length,
      active: active.length,
      dismissed: this.notificationHistory.filter(n => n.dismissed).length,
      byType,
      byRisk
    };
  }
}
