/**
 * Notification Store
 * Zustand store for notification state management
 */

import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
import {
  notificationApi,
  type Notification,
  type NotificationPreferences,
} from '../services/notification.service';
import { tradingWS } from '../services/websocket.service';

// ============================================================================
// Types
// ============================================================================

interface NotificationState {
  // State
  notifications: Notification[];
  unreadCount: number;
  preferences: NotificationPreferences | null;
  loading: boolean;
  error: string | null;

  // Actions
  fetchNotifications: (unreadOnly?: boolean) => Promise<void>;
  fetchUnreadCount: () => Promise<void>;
  fetchPreferences: () => Promise<void>;
  markAsRead: (id: string) => Promise<void>;
  markAllAsRead: () => Promise<void>;
  deleteNotification: (id: string) => Promise<void>;
  updatePreferences: (updates: Partial<NotificationPreferences>) => Promise<void>;
  addNotification: (notification: Notification) => void;
  clearError: () => void;

  // WebSocket
  initializeWebSocket: () => () => void;
}

// ============================================================================
// Store
// ============================================================================

export const useNotificationStore = create<NotificationState>()(
  devtools(
    (set, get) => ({
      // Initial state
      notifications: [],
      unreadCount: 0,
      preferences: null,
      loading: false,
      error: null,

      // Fetch notifications
      fetchNotifications: async (unreadOnly = false) => {
        set({ loading: true, error: null });
        try {
          const notifications = await notificationApi.getNotifications({
            limit: 50,
            unreadOnly,
          });
          set({ notifications, loading: false });
        } catch (error) {
          const errorMessage = error instanceof Error ? error.message : 'Failed to fetch notifications';
          set({ error: errorMessage, loading: false });
        }
      },

      // Fetch unread count
      fetchUnreadCount: async () => {
        try {
          const unreadCount = await notificationApi.getUnreadCount();
          set({ unreadCount });
        } catch (error) {
          console.error('Failed to fetch unread count:', error);
        }
      },

      // Fetch preferences
      fetchPreferences: async () => {
        try {
          const preferences = await notificationApi.getPreferences();
          set({ preferences });
        } catch (error) {
          console.error('Failed to fetch preferences:', error);
        }
      },

      // Mark notification as read
      markAsRead: async (id: string) => {
        try {
          await notificationApi.markAsRead(id);

          set((state) => ({
            notifications: state.notifications.map((n) =>
              n.id === id ? { ...n, isRead: true, readAt: new Date().toISOString() } : n
            ),
            unreadCount: Math.max(0, state.unreadCount - 1),
          }));
        } catch (error) {
          console.error('Failed to mark as read:', error);
        }
      },

      // Mark all as read
      markAllAsRead: async () => {
        try {
          await notificationApi.markAllAsRead();

          set((state) => ({
            notifications: state.notifications.map((n) => ({
              ...n,
              isRead: true,
              readAt: new Date().toISOString(),
            })),
            unreadCount: 0,
          }));
        } catch (error) {
          console.error('Failed to mark all as read:', error);
        }
      },

      // Delete notification
      deleteNotification: async (id: string) => {
        try {
          await notificationApi.deleteNotification(id);

          set((state) => {
            const notification = state.notifications.find((n) => n.id === id);
            const wasUnread = notification && !notification.isRead;

            return {
              notifications: state.notifications.filter((n) => n.id !== id),
              unreadCount: wasUnread ? Math.max(0, state.unreadCount - 1) : state.unreadCount,
            };
          });
        } catch (error) {
          console.error('Failed to delete notification:', error);
        }
      },

      // Update preferences
      updatePreferences: async (updates) => {
        try {
          const preferences = await notificationApi.updatePreferences(updates);
          set({ preferences });
        } catch (error) {
          console.error('Failed to update preferences:', error);
        }
      },

      // Add notification (from WebSocket)
      addNotification: (notification: Notification) => {
        set((state) => ({
          notifications: [notification, ...state.notifications].slice(0, 100),
          unreadCount: state.unreadCount + 1,
        }));
      },

      // Clear error
      clearError: () => {
        set({ error: null });
      },

      // Initialize WebSocket subscription
      initializeWebSocket: () => {
        const handleNotification = (data: unknown) => {
          const notification = data as Notification;
          get().addNotification(notification);
        };

        const unsubscribe = tradingWS.subscribe('notification', handleNotification);

        // Return cleanup function
        return unsubscribe;
      },
    }),
    {
      name: 'notification-store',
    }
  )
);

// ============================================================================
// Selectors
// ============================================================================

export const useNotifications = () => useNotificationStore((state) => state.notifications);
export const useUnreadCount = () => useNotificationStore((state) => state.unreadCount);
export const useNotificationPreferences = () => useNotificationStore((state) => state.preferences);
export const useNotificationsLoading = () => useNotificationStore((state) => state.loading);

export default useNotificationStore;
