/**
 * @fileoverview A popover component to display user notifications.
 * Grouped by date (Today, Yesterday, Earlier) with mark as read support.
 */
import notificationService from '../services/notification-service.js';

class DsNotificationCenter extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this._isConnected = false;
  }

  connectedCallback() {
    this._isConnected = true;
    this.render();
    this._updateNotifications = this._updateNotifications.bind(this);
    notificationService.addEventListener('notifications-updated', this._updateNotifications);

    // Initialize the service and get initial notifications
    // Only update if component is still connected when promise resolves
    notificationService.init().then(() => {
      if (this._isConnected) {
        this._updateNotifications({ detail: { notifications: notificationService.getAll() } });
      }
    }).catch((error) => {
      console.error('[DsNotificationCenter] Failed to initialize notifications:', error);
    });

    this.shadowRoot.getElementById('mark-all-read').addEventListener('click', () => {
      notificationService.markAllAsRead();
    });

    this.shadowRoot.getElementById('clear-all').addEventListener('click', () => {
      notificationService.clearAll();
    });

    this.shadowRoot.getElementById('notification-list').addEventListener('click', this._handleNotificationClick.bind(this));
  }

  disconnectedCallback() {
    this._isConnected = false;
    notificationService.removeEventListener('notifications-updated', this._updateNotifications);
  }

  _handleNotificationClick(e) {
    const notificationEl = e.target.closest('.notification');
    if (!notificationEl) return;

    const id = notificationEl.dataset.id;
    if (!id) return;

    // Mark as read if it was unread
    if (notificationEl.classList.contains('unread')) {
      notificationService.markAsRead(id);
    }

    // Handle action button clicks
    const actionButton = e.target.closest('[data-event]');
    if (actionButton) {
      let payload = {};
      try {
        payload = JSON.parse(actionButton.dataset.payload || '{}');
      } catch (e) {
        console.error('Invalid action payload:', e);
      }

      this.dispatchEvent(new CustomEvent('notification-action', {
        bubbles: true,
        composed: true,
        detail: {
          event: actionButton.dataset.event,
          payload
        }
      }));

      // Close the notification center
      this.removeAttribute('open');
    }

    // Handle delete button
    const deleteButton = e.target.closest('.delete-btn');
    if (deleteButton) {
      e.stopPropagation();
      notificationService.delete(id);
    }
  }

  _updateNotifications({ detail }) {
    const { notifications } = detail;
    const listEl = this.shadowRoot?.getElementById('notification-list');

    // Null safety check - component may be disconnecting
    if (!listEl) {
      console.warn('[DsNotificationCenter] Notification list element not found');
      return;
    }

    if (!notifications || notifications.length === 0) {
      listEl.innerHTML = `
        <div class="empty-state">
          <svg width="48" height="48" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
            <path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/>
            <path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/>
          </svg>
          <p>No notifications yet</p>
          <span>You're all caught up!</span>
        </div>
      `;
      return;
    }

    const grouped = this._groupNotificationsByDate(notifications);

    let html = '';
    for (const [groupTitle, groupNotifications] of Object.entries(grouped)) {
      html += `
        <div class="group">
          <div class="group__title">${groupTitle}</div>
          ${groupNotifications.map(n => this._renderNotification(n)).join('')}
        </div>
      `;
    }
    listEl.innerHTML = html;
  }

  _groupNotificationsByDate(notifications) {
    const groups = {};
    const today = new Date();
    const yesterday = new Date(today);
    yesterday.setDate(yesterday.getDate() - 1);

    const isSameDay = (d1, d2) =>
      d1.getFullYear() === d2.getFullYear() &&
      d1.getMonth() === d2.getMonth() &&
      d1.getDate() === d2.getDate();

    notifications.forEach(n => {
      const date = new Date(n.timestamp);
      let groupName;

      if (isSameDay(date, today)) {
        groupName = 'Today';
      } else if (isSameDay(date, yesterday)) {
        groupName = 'Yesterday';
      } else {
        groupName = 'Earlier';
      }

      if (!groups[groupName]) {
        groups[groupName] = [];
      }
      groups[groupName].push(n);
    });

    return groups;
  }

  _renderNotification(n) {
    const time = new Date(n.timestamp).toLocaleTimeString([], {
      hour: '2-digit',
      minute: '2-digit'
    });

    const actionsHtml = (n.actions || []).map(action =>
      `<button class="action-btn" data-event="${action.event}" data-payload='${JSON.stringify(action.payload || {})}'>${action.label}</button>`
    ).join('');

    return `
      <div class="notification ${n.read ? '' : 'unread'}" data-id="${n.id}">
        <div class="icon-container">
          <div class="dot ${n.type || 'info'}"></div>
        </div>
        <div class="notification-content">
          <p class="title">${this._escapeHtml(n.title)}</p>
          ${n.message ? `<p class="message">${this._escapeHtml(n.message)}</p>` : ''}
          <div class="meta">
            <span class="time">${time}</span>
            ${n.source ? `<span class="source">${n.source}</span>` : ''}
          </div>
          ${actionsHtml ? `<div class="actions">${actionsHtml}</div>` : ''}
        </div>
        <button class="delete-btn" aria-label="Delete notification">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <line x1="18" y1="6" x2="6" y2="18"></line>
            <line x1="6" y1="6" x2="18" y2="18"></line>
          </svg>
        </button>
      </div>
    `;
  }

  _escapeHtml(text) {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
  }

  render() {
    this.shadowRoot.innerHTML = `
      <style>
        :host {
          display: none;
          position: absolute;
          top: calc(100% + var(--space-2));
          right: 0;
          width: 380px;
          z-index: 100;
        }
        :host([open]) {
          display: block;
        }
        .panel {
          background: var(--popover);
          color: var(--popover-foreground);
          border: 1px solid var(--border);
          border-radius: var(--radius-lg);
          box-shadow: var(--shadow-lg);
          display: flex;
          flex-direction: column;
          max-height: 480px;
          overflow: hidden;
        }
        .header {
          display: flex;
          justify-content: space-between;
          align-items: center;
          padding: var(--space-3) var(--space-4);
          border-bottom: 1px solid var(--border);
          flex-shrink: 0;
        }
        .header h3 {
          margin: 0;
          font-size: var(--text-base);
          font-weight: var(--font-semibold);
        }
        .header-actions {
          display: flex;
          gap: var(--space-2);
        }
        .header-actions button {
          font-size: var(--text-xs);
          color: var(--primary);
          cursor: pointer;
          background: none;
          border: none;
          padding: 0;
        }
        .header-actions button:hover {
          text-decoration: underline;
        }
        .content {
          overflow-y: auto;
          flex: 1;
        }
        .empty-state {
          text-align: center;
          padding: var(--space-8);
          color: var(--muted-foreground);
        }
        .empty-state svg {
          opacity: 0.5;
          margin-bottom: var(--space-3);
        }
        .empty-state p {
          margin: 0;
          font-size: var(--text-sm);
          font-weight: var(--font-medium);
          color: var(--foreground);
        }
        .empty-state span {
          font-size: var(--text-xs);
        }
        .group {
          border-bottom: 1px solid var(--border);
        }
        .group:last-child {
          border-bottom: none;
        }
        .group__title {
          padding: var(--space-2) var(--space-4);
          font-size: var(--text-xs);
          font-weight: var(--font-medium);
          color: var(--muted-foreground);
          text-transform: uppercase;
          letter-spacing: 0.05em;
          background: var(--muted);
        }
        .notification {
          display: flex;
          gap: var(--space-3);
          padding: var(--space-3) var(--space-4);
          position: relative;
          cursor: pointer;
          transition: background 0.15s ease;
        }
        .notification.unread {
          background-color: oklch(from var(--primary) l c h / 0.05);
        }
        .notification:hover {
          background-color: var(--accent);
        }
        .icon-container {
          flex-shrink: 0;
          width: 10px;
          padding-top: 4px;
        }
        .dot {
          width: 8px;
          height: 8px;
          border-radius: 50%;
        }
        .dot.info { background-color: var(--primary); }
        .dot.success { background-color: var(--success); }
        .dot.warning { background-color: var(--warning); }
        .dot.error { background-color: var(--destructive); }

        .notification-content {
          flex: 1;
          min-width: 0;
        }
        .notification-content .title {
          margin: 0;
          font-size: var(--text-sm);
          font-weight: var(--font-medium);
          color: var(--foreground);
          line-height: 1.3;
        }
        .notification-content .message {
          margin: var(--space-1) 0 0;
          font-size: var(--text-xs);
          color: var(--muted-foreground);
          line-height: 1.4;
        }
        .meta {
          display: flex;
          gap: var(--space-2);
          font-size: var(--text-xs);
          color: var(--muted-foreground);
          margin-top: var(--space-1);
        }
        .source {
          background: var(--muted);
          padding: 0 var(--space-1);
          border-radius: var(--radius-sm);
        }
        .actions {
          margin-top: var(--space-2);
          display: flex;
          gap: var(--space-2);
        }
        .action-btn {
          font-size: var(--text-xs);
          padding: var(--space-1) var(--space-2);
          background: var(--muted);
          border: 1px solid var(--border);
          color: var(--foreground);
          border-radius: var(--radius-sm);
          cursor: pointer;
          transition: background 0.15s ease;
        }
        .action-btn:hover {
          background: var(--accent);
        }
        .delete-btn {
          position: absolute;
          top: var(--space-2);
          right: var(--space-2);
          background: none;
          border: none;
          color: var(--muted-foreground);
          cursor: pointer;
          padding: var(--space-1);
          border-radius: var(--radius);
          opacity: 0;
          transition: opacity 0.15s ease;
        }
        .notification:hover .delete-btn {
          opacity: 1;
        }
        .delete-btn:hover {
          background: var(--destructive);
          color: white;
        }
      </style>
      <div class="panel">
        <div class="header">
          <h3>Notifications</h3>
          <div class="header-actions">
            <button id="mark-all-read">Mark all read</button>
            <button id="clear-all">Clear all</button>
          </div>
        </div>
        <div class="content" id="notification-list">
          <!-- Notifications will be rendered here -->
        </div>
      </div>
    `;
  }
}

customElements.define('ds-notification-center', DsNotificationCenter);
