// src/client/entities/notification.ts
// Notification entity - Pinia store for centralized notification management

import { defineStore } from 'pinia';
import { api } from '../shared/api';
import { useUserStore } from './user';
import { useNoteStore } from './note';

// Notification interface
export interface Notification {
  id: string;
  event: string;
  data: any;
  readAt: string | null;
  createdAt: string;
}

// Notification store
export const useNotificationStore = defineStore('notification', {
  state: (): {
    notifications: Notification[];
    loading: boolean;
    error: string | null;
  } => ({
    notifications: [],
    loading: false,
    error: null,
  }),

  getters: {
    unreadCount: (state) => {
      return state.notifications.filter((n) => !n.readAt).length;
    },
    
    // Count of unread shift-related notifications (shift:* and approval:*)
    shiftCount: (state) => {
      return state.notifications.filter((n) => 
        !n.readAt && (n.event.startsWith('shift:') || n.event.startsWith('approval:'))
      ).length;
    },
    
    // Count of unread note-related notifications (note:* and mention:*)
    noteCount: (state) => {
      return state.notifications.filter((n) => 
        !n.readAt && (n.event.startsWith('note:') || n.event.startsWith('mention:'))
      ).length;
    },
  },

  actions: {
    async fetchNotifications(): Promise<void> {
      this.loading = true;
      this.error = null;
      try {
        const userStore = useUserStore();
        const userId = userStore.user?.id;
        
        if (!userId) {
          throw new Error('User not authenticated');
        }

        console.log(`[NotificationStore] Fetching notifications for user ${userId}...`);
        const response = await api.get<Notification[]>(`/notifications/${userId}`);
        console.log(`[NotificationStore] Received ${response.length} notifications:`, response);
        this.notifications = response;
      } catch (error: any) {
        this.error = error.message || 'Failed to fetch notifications';
        throw error;
      } finally {
        this.loading = false;
      }
    },

    async markAsRead(id: string): Promise<void> {
      this.loading = true;
      this.error = null;
      try {
        await api.post(`/notifications/${id}/read`, {});
        
        // Update local state
        const notification = this.notifications.find((n) => n.id === id);
        if (notification) {
          notification.readAt = new Date().toISOString();
        }
      } catch (error: any) {
        this.error = error.message || 'Failed to mark notification as read';
        throw error;
      } finally {
        this.loading = false;
      }
    },

    async markAllAsRead(): Promise<void> {
      this.loading = true;
      this.error = null;
      try {
        const userStore = useUserStore();
        const userId = userStore.user?.id;
        
        if (!userId) {
          throw new Error('User not authenticated');
        }

        await api.post(`/notifications/user/${userId}/read-all`, {});
        
        // Update local state
        this.notifications.forEach((n) => {
          n.readAt = new Date().toISOString();
        });
      } catch (error: any) {
        this.error = error.message || 'Failed to mark all notifications as read';
        throw error;
      } finally {
        this.loading = false;
      }
    },

    // Local actions
    addNotification(notification: Notification) {
      console.log('[Socket] New notification received:', notification);
      console.log('Attempting to remove notification with ID:', notification.id, 'Current notifications IDs:', this.notifications.map(n => n.id));

      // NEW: Bridge Socket -> NoteStore for real-time comment updates
      // If this is a comment event, extract and push comment to noteStore
      if (notification.event === 'note:commented' && notification.data?.comment) {
        const noteStore = useNoteStore();
        const comment = notification.data.comment;

        // Push comment to store for instant UI reaction
        noteStore.comments.push(comment);
        console.log('[Socket] Comment pushed to noteStore:', comment);
      }

      // Socket Bridge: Update note dates for mention/note events
      // This triggers immediate UI reaction (pulse/red indicators) before modal opens
      if ((notification.event.startsWith('mention:') || notification.event.startsWith('note:')) &&
          notification.data?.noteId &&
          notification.data?.lastCommentAt) {
        const noteStore = useNoteStore();
        // If this is a mention event, set isMentioned to true to update lastMentionAt
        const isMentioned = notification.event.startsWith('mention:');
        noteStore.patchNoteDates(
          notification.data.noteId,
          notification.data.lastCommentAt,
          notification.data.lastCommentAuthorId,
          isMentioned
        );
        console.log('[Socket] Updated note dates for noteId:', notification.data.noteId, 'isMentioned:', isMentioned);
      }

      // Special handler for mention:notification event
      // Forces immediate mention highlight when push notification arrives
      if (notification.event === 'mention:notification') {
        const noteStore = useNoteStore();
        const updateTime = notification.data.lastCommentAt || notification.createdAt;
        noteStore.patchNoteDates(notification.data.noteId, updateTime, notification.data.authorId, true, notification.createdAt);
        console.log('[SOCKET_BRIDGE_SUCCESS] Mention triggered for:', notification.data.noteId);
      }

      // 1. Если пришло обнуление — вырезаем через filter для гарантированной реактивности
      if (notification.data?.isGrouped === true && notification.data?.count === 0) {
        this.notifications = this.notifications.filter(n => n.id !== notification.id);
        console.log('[Socket] Notification filtered out (count 0):', notification.id);
        return;
      }

      // 2. Логика обновления/добавления
      const index = this.notifications.findIndex(n => n.id === notification.id);
      if (index !== -1) {
        // Используем spread для создания нового объекта (реактивность)
        this.notifications[index] = { ...this.notifications[index], ...notification };
      } else {
        this.notifications.unshift(notification);
      }
    },

    clearError() {
      this.error = null;
    },
  },

  persist: true,
});
