/**
 * useEventNotifications Hook
 *
 * Subscribe to lightweight informational notifications from the new event architecture.
 * Subscribes to domain-specific notification channels via SSE.
 *
 * Examples:
 *   const { notifications } = useEventNotifications(); // All notifications
 *   const { notifications } = useEventNotifications({ domains: ['production'], maxAge: 3600 });
 *   const { notifications } = useEventNotifications({ eventTypes: ['batch_completed', 'batch_started'] });
 */

import { useState, useEffect, useMemo, useCallback, useRef } from 'react';
import { useSSEEvents } from './useSSE';
import type {
  Notification,
  EventDomain,
  UseNotificationsConfig,
} from '../api/types/events';
import { isNotification } from '../api/types/events';

interface UseEventNotificationsReturn {
  notifications: Notification[];
  recentNotifications: Notification[];
  isLoading: boolean;
  isConnected: boolean; // Added isConnected to interface
  clearNotifications: () => void;
}

const DEFAULT_MAX_AGE = 3600; // 1 hour

export function useEventNotifications(config: UseNotificationsConfig = {}): UseEventNotificationsReturn {
  const {
    domains,
    eventTypes,
    maxAge = DEFAULT_MAX_AGE,
  } = config;

  // Determine which channels to subscribe to
  const channels = useMemo(() => {
    if (!domains || domains.length === 0) {
      // Subscribe to all notification channels
      return ['*.notifications'];
    }
    // Subscribe to specific domain notification channels
    return domains.map(domain => `${domain}.notifications`);
  }, [domains]);

  // Subscribe to SSE with channel filter
  const { events, isConnected } = useSSEEvents({ channels });

  // Filter events to notifications only
  const [notifications, setNotifications] = useState<Notification[]>([]);
  const [isLoading, setIsLoading] = useState(true);

  // Use refs to track previous values and prevent unnecessary updates
  const prevEventIdsRef = useRef<string>('');
  const prevEventTypesRef = useRef<string[]>([]);
  const prevMaxAgeRef = useRef<number>(maxAge);
  const prevDomainsRef = useRef<string[]>(domains || []);

  useEffect(() => {
    // Check if the configuration has actually changed
    const currentEventTypes = eventTypes || [];
    const currentDomains = domains || [];

    const configChanged =
      JSON.stringify(currentEventTypes) !== JSON.stringify(prevEventTypesRef.current) ||
      prevMaxAgeRef.current !== maxAge ||
      JSON.stringify(currentDomains) !== JSON.stringify(prevDomainsRef.current);

    // Update refs with current values
    prevEventTypesRef.current = currentEventTypes;
    prevMaxAgeRef.current = maxAge;
    prevDomainsRef.current = currentDomains;

    // Create current event IDs string for comparison
    const currentEventIds = events.map(e => e.id).join(',');

    // Only process if config changed OR events actually changed
    if (!configChanged && currentEventIds === prevEventIdsRef.current) {
      return; // No changes, skip processing
    }

    // Update the previous event IDs
    prevEventIdsRef.current = currentEventIds;

    console.log('🔵 [useEventNotifications] Effect triggered', {
      eventsCount: events.length,
      eventTypes,
      maxAge,
      domains,
      channels,
    });

    // Filter and process incoming events
    const notificationEvents = events.filter(isNotification);
    console.log('🔵 [useEventNotifications] After isNotification filter:', {
      notificationEventsCount: notificationEvents.length,
      eventIds: notificationEvents.map(e => e.id).join(','),
    });

    // Apply filters
    let filtered = notificationEvents;

    // Filter by event types
    if (eventTypes && eventTypes.length > 0) {
      filtered = filtered.filter(notification =>
        eventTypes.includes(notification.event_type)
      );
      console.log('🔵 [useEventNotifications] After event type filter:', {
        filteredCount: filtered.length,
        requestedTypes: eventTypes,
      });
    }

    // Filter by age (maxAge in seconds)
    if (maxAge) {
      const maxAgeMs = maxAge * 1000;
      const now = Date.now();
      filtered = filtered.filter(notification => {
        const notificationTime = new Date(notification.created_at).getTime();
        return now - notificationTime <= maxAgeMs;
      });
      console.log('🔵 [useEventNotifications] After age filter:', {
        filteredCount: filtered.length,
        maxAge,
      });
    }

    // Filter expired notifications (TTL)
    filtered = filtered.filter(notification => {
      if (notification.expires_at) {
        const expiryTime = new Date(notification.expires_at).getTime();
        return Date.now() < expiryTime;
      }
      return true;
    });
    console.log('🔵 [useEventNotifications] After expiry filter:', {
      filteredCount: filtered.length,
    });

    // Sort by timestamp (newest first)
    filtered.sort((a, b) => {
      const timeA = new Date(a.created_at).getTime();
      const timeB = new Date(b.created_at).getTime();
      return timeB - timeA;
    });

    console.log('🔵 [useEventNotifications] Setting notifications state', {
      filteredCount: filtered.length,
      filteredIds: filtered.map(n => n.id).join(','),
      firstId: filtered[0]?.id,
    });

    // Only update state if the IDs have actually changed to prevent infinite loops
    setNotifications(prev => {
      const prevIds = prev.map(n => n.id).join(',');
      const newIds = filtered.map(n => n.id).join(',');

      console.log('🔵 [useEventNotifications] Comparing IDs:', {
        prevIds,
        newIds,
        hasChanged: prevIds !== newIds,
      });

      if (prevIds === newIds) {
        console.log('🔵 [useEventNotifications] IDs unchanged, keeping previous array reference');
        return prev; // Keep same reference if IDs haven't changed
      }

      console.log('🔵 [useEventNotifications] IDs changed, updating state');
      return filtered;
    });
    setIsLoading(false);
  }, [events, eventTypes, maxAge, domains, channels]); // Include all dependencies

  // Computed values
  const recentNotifications = useMemo(() => {
    // Last 10 notifications
    return notifications.slice(0, 10);
  }, [notifications]);

  const clearNotifications = useCallback(() => {
    setNotifications([]);
  }, []);

  return {
    notifications,
    recentNotifications,
    isLoading: isLoading || !isConnected,
    isConnected, // Added this missing return property
    clearNotifications,
  };
}

/**
 * useNotificationsByDomain Hook
 *
 * Get notifications grouped by domain.
 */
export function useNotificationsByDomain(config: UseNotificationsConfig = {}) {
  const { notifications, ...rest } = useEventNotifications(config);

  const notificationsByDomain = useMemo(() => {
    const grouped: Partial<Record<EventDomain, Notification[]>> = {};

    notifications.forEach(notification => {
      if (!grouped[notification.event_domain]) {
        grouped[notification.event_domain] = [];
      }
      grouped[notification.event_domain]!.push(notification);
    });

    return grouped;
  }, [notifications]);

  return {
    notifications,
    notificationsByDomain,
    ...rest,
  };
}

/**
 * useProductionNotifications Hook
 *
 * Convenience hook for production domain notifications.
 */
export function useProductionNotifications(eventTypes?: string[]) {
  return useEventNotifications({
    domains: ['production'],
    eventTypes,
  });
}

/**
 * useInventoryNotifications Hook
 *
 * Convenience hook for inventory domain notifications.
 */
export function useInventoryNotifications(eventTypes?: string[]) {
  return useEventNotifications({
    domains: ['inventory'],
    eventTypes,
  });
}

/**
 * useSupplyChainNotifications Hook
 *
 * Convenience hook for supply chain domain notifications.
 */
export function useSupplyChainNotifications(eventTypes?: string[]) {
  return useEventNotifications({
    domains: ['supply_chain'],
    eventTypes,
  });
}

/**
 * useOperationsNotifications Hook
 *
 * Convenience hook for operations domain notifications (orchestration).
 */
export function useOperationsNotifications(eventTypes?: string[]) {
  return useEventNotifications({
    domains: ['operations'],
    eventTypes,
  });
}

/**
 * useBatchNotifications Hook
 *
 * Convenience hook for production batch-related notifications.
 */
export function useBatchNotifications() {
  return useEventNotifications({
    domains: ['production'],
    eventTypes: [
      'batch_state_changed',
      'batch_completed',
      'batch_started',
    ],
  });
}

/**
 * useDeliveryNotifications Hook
 *
 * Convenience hook for delivery-related notifications.
 */
export function useDeliveryNotifications() {
  return useEventNotifications({
    domains: ['supply_chain'],
    eventTypes: [
      'delivery_scheduled',
      'delivery_arriving_soon',
      'delivery_received',
    ],
  });
}

/**
 * useOrchestrationNotifications Hook
 *
 * Convenience hook for orchestration run notifications.
 */
export function useOrchestrationNotifications() {
  return useEventNotifications({
    domains: ['operations'],
    eventTypes: [
      'orchestration_run_started',
      'orchestration_run_completed',
      'action_created',
      'action_completed',
    ],
  });
}
