/**
 * Notification Toast Component
 *
 * Displays real-time notifications as toast messages.
 */

import React, { useEffect, useState, useCallback } from 'react';
import classNames from 'classnames';
import { useSocketContext } from '../../lib/realtime/SocketContext';
import type { RealtimeNotification } from '../../lib/realtime/types';

interface NotificationToastProps {
  position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
  maxVisible?: number;
  autoHideDuration?: number;
  className?: string;
}

/**
 * Get position classes
 */
function getPositionClasses(position: NotificationToastProps['position']): string {
  switch (position) {
    case 'top-left':
      return 'top-4 left-4';
    case 'bottom-right':
      return 'bottom-4 right-4';
    case 'bottom-left':
      return 'bottom-4 left-4';
    case 'top-right':
    default:
      return 'top-4 right-4';
  }
}

/**
 * Get notification type styles
 */
function getTypeStyles(type: RealtimeNotification['type']): {
  bg: string;
  border: string;
  icon: string;
  iconColor: string;
} {
  switch (type) {
    case 'success':
      return {
        bg: 'bg-green-50',
        border: 'border-green-200',
        icon: '✓',
        iconColor: 'text-green-600',
      };
    case 'warning':
      return {
        bg: 'bg-yellow-50',
        border: 'border-yellow-200',
        icon: '⚠',
        iconColor: 'text-yellow-600',
      };
    case 'error':
      return {
        bg: 'bg-red-50',
        border: 'border-red-200',
        icon: '✕',
        iconColor: 'text-red-600',
      };
    case 'info':
    default:
      return {
        bg: 'bg-blue-50',
        border: 'border-blue-200',
        icon: 'ℹ',
        iconColor: 'text-blue-600',
      };
  }
}

/**
 * Single toast notification
 */
function Toast({
  notification,
  onDismiss,
  autoHideDuration,
}: {
  notification: RealtimeNotification;
  onDismiss: (id: string) => void;
  autoHideDuration: number;
}) {
  const [isVisible, setIsVisible] = useState(false);
  const [isLeaving, setIsLeaving] = useState(false);
  const styles = getTypeStyles(notification.type);

  // Animate in
  useEffect(() => {
    const timer = setTimeout(() => setIsVisible(true), 10);
    return () => clearTimeout(timer);
  }, []);

  // Auto hide
  useEffect(() => {
    if (autoHideDuration <= 0) return;

    const timer = setTimeout(() => {
      handleDismiss();
    }, autoHideDuration);

    return () => clearTimeout(timer);
  }, [autoHideDuration]);

  const handleDismiss = useCallback(() => {
    setIsLeaving(true);
    setTimeout(() => {
      onDismiss(notification.id);
    }, 300);
  }, [notification.id, onDismiss]);

  return (
    <div
      className={classNames(
        'max-w-sm w-full p-4 rounded-lg border shadow-lg transition-all duration-300',
        styles.bg,
        styles.border,
        {
          'opacity-0 translate-x-4': !isVisible || isLeaving,
          'opacity-100 translate-x-0': isVisible && !isLeaving,
        }
      )}
      role="alert"
    >
      <div className="flex items-start gap-3">
        {/* Icon */}
        <span className={classNames('text-xl font-bold flex-shrink-0', styles.iconColor)}>
          {styles.icon}
        </span>

        {/* Content */}
        <div className="flex-1 min-w-0">
          <h4 className="font-medium text-gray-900 text-sm">
            {notification.title}
          </h4>
          <p className="text-sm text-gray-600 mt-1">
            {notification.message}
          </p>
        </div>

        {/* Close button */}
        <button
          onClick={handleDismiss}
          className="flex-shrink-0 text-gray-400 hover:text-gray-600 transition-colors"
          aria-label="Dismiss notification"
        >
          <svg className="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
            <path
              fillRule="evenodd"
              d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
              clipRule="evenodd"
            />
          </svg>
        </button>
      </div>
    </div>
  );
}

/**
 * Notification Toast container
 */
export function NotificationToast({
  position = 'top-right',
  maxVisible = 5,
  autoHideDuration = 5000,
  className,
}: NotificationToastProps) {
  const { notifications, dismissNotification } = useSocketContext();

  // Only show non-read, non-dismissed notifications
  const visibleNotifications = notifications
    .filter((n) => !n.read && !n.dismissed)
    .slice(0, maxVisible);

  if (visibleNotifications.length === 0) {
    return null;
  }

  return (
    <div
      className={classNames(
        'fixed z-50 flex flex-col gap-2',
        getPositionClasses(position),
        className
      )}
    >
      {visibleNotifications.map((notification) => (
        <Toast
          key={notification.id}
          notification={notification}
          onDismiss={dismissNotification}
          autoHideDuration={autoHideDuration}
        />
      ))}
    </div>
  );
}

/**
 * Notification bell with badge
 */
export function NotificationBell({
  onClick,
  className,
}: {
  onClick?: () => void;
  className?: string;
}) {
  const { unreadCount } = useSocketContext();

  return (
    <button
      onClick={onClick}
      className={classNames(
        'relative p-2 text-gray-600 hover:text-gray-900 transition-colors',
        className
      )}
      aria-label={`Notifications${unreadCount > 0 ? ` (${unreadCount} unread)` : ''}`}
    >
      {/* Bell icon */}
      <svg
        className="w-6 h-6"
        fill="none"
        stroke="currentColor"
        viewBox="0 0 24 24"
      >
        <path
          strokeLinecap="round"
          strokeLinejoin="round"
          strokeWidth={2}
          d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"
        />
      </svg>

      {/* Badge */}
      {unreadCount > 0 && (
        <span className="absolute top-0 right-0 inline-flex items-center justify-center px-1.5 py-0.5 text-xs font-bold leading-none text-white transform translate-x-1/2 -translate-y-1/2 bg-red-500 rounded-full">
          {unreadCount > 99 ? '99+' : unreadCount}
        </span>
      )}
    </button>
  );
}

/**
 * Notification list dropdown
 */
export function NotificationList({
  className,
  onClose,
}: {
  className?: string;
  onClose?: () => void;
}) {
  const { notifications, markNotificationRead, markAllRead } = useSocketContext();

  return (
    <div
      className={classNames(
        'w-80 max-h-96 bg-white rounded-lg shadow-lg border border-gray-200 overflow-hidden',
        className
      )}
    >
      {/* Header */}
      <div className="flex items-center justify-between px-4 py-3 border-b border-gray-200 bg-gray-50">
        <h3 className="font-semibold text-gray-900">Notifications</h3>
        {notifications.length > 0 && (
          <button
            onClick={markAllRead}
            className="text-sm text-blue-600 hover:text-blue-800"
          >
            Mark all read
          </button>
        )}
      </div>

      {/* List */}
      <div className="overflow-y-auto max-h-72">
        {notifications.length === 0 ? (
          <div className="py-8 text-center text-gray-500">
            <div className="text-3xl mb-2">🔔</div>
            <p className="text-sm">No notifications</p>
          </div>
        ) : (
          notifications.map((notification) => (
            <div
              key={notification.id}
              className={classNames(
                'px-4 py-3 border-b border-gray-100 hover:bg-gray-50 cursor-pointer transition-colors',
                { 'bg-blue-50': !notification.read }
              )}
              onClick={() => markNotificationRead(notification.id)}
            >
              <div className="flex items-start gap-2">
                <span className="text-lg">
                  {getTypeStyles(notification.type).icon}
                </span>
                <div className="flex-1 min-w-0">
                  <p className={classNames('text-sm', { 'font-medium': !notification.read })}>
                    {notification.title}
                  </p>
                  <p className="text-xs text-gray-500 truncate">
                    {notification.message}
                  </p>
                  <p className="text-xs text-gray-400 mt-1">
                    {new Date(notification.timestamp).toLocaleTimeString()}
                  </p>
                </div>
              </div>
            </div>
          ))
        )}
      </div>
    </div>
  );
}

export default NotificationToast;
