/**
 * useNotifications Hook
 * 
 * Hook for managing in-app notifications.
 * Supports fetching, marking as read, and executing actions.
 */

import { useState, useCallback, useEffect, useRef } from 'react';
import api from '../api';

// Types
export interface NotificationAction {
  actionId: string;
  label: string;
  style: 'primary' | 'danger' | 'default';
}

export interface UserNotification {
  id: string;
  userId: string;
  type: 'invitation' | 'system' | 'workflow' | 'mention';
  status: 'unread' | 'read' | 'actioned' | 'dismissed';
  title: string;
  message: string;
  icon?: string;
  referenceType?: string;
  referenceId?: string;
  actions?: NotificationAction[];
  actionTaken?: string;
  actionResult?: string;
  createdAt: number;
  readAt?: number;
  actionedAt?: number;
  expiresAt?: number;
}

export interface NotificationActionResult {
  message: string;
  action: string;
  notificationId: string;
}

/**
 * Hook for managing notifications
 */
export function useNotifications() {
  const [notifications, setNotifications] = useState<UserNotification[]>([]);
  const [unreadCount, setUnreadCount] = useState<number>(0);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  
  // Polling interval ref
  const pollingIntervalRef = useRef<NodeJS.Timeout | null>(null);

  /**
   * Fetch all notifications for the current user
   */
  const fetchNotifications = useCallback(async (
    options?: { status?: string; type?: string; limit?: number }
  ): Promise<UserNotification[]> => {
    setLoading(true);
    setError(null);
    
    try {
      const params = new URLSearchParams();
      if (options?.status) params.append('status', options.status);
      if (options?.type) params.append('type', options.type);
      if (options?.limit) params.append('limit', options.limit.toString());
      
      const queryString = params.toString();
      const url = `/api/notifications${queryString ? `?${queryString}` : ''}`;
      
      const response = await api.get(url);
      const data = response.data as UserNotification[];
      setNotifications(data);
      return data;
    } catch (err: any) {
      const errorMessage = err.response?.data?.detail || 'Fehler beim Laden der Benachrichtigungen';
      setError(errorMessage);
      return [];
    } finally {
      setLoading(false);
    }
  }, []);

  /**
   * Fetch unread count
   */
  const fetchUnreadCount = useCallback(async (): Promise<number> => {
    try {
      const response = await api.get('/api/notifications/unread-count');
      const count = response.data.count;
      setUnreadCount(count);
      return count;
    } catch (err: any) {
      console.error('Failed to fetch unread count:', err);
      return 0;
    }
  }, []);

  /**
   * Mark a notification as read
   */
  const markAsRead = useCallback(async (notificationId: string): Promise<boolean> => {
    try {
      await api.put(`/api/notifications/${notificationId}/read`);
      
      // Update local state
      setNotifications(prev => 
        prev.map(n => 
          n.id === notificationId 
            ? { ...n, status: 'read' as const, readAt: Date.now() / 1000 }
            : n
        )
      );
      
      // Update unread count
      setUnreadCount(prev => Math.max(0, prev - 1));
      
      return true;
    } catch (err: any) {
      console.error('Failed to mark notification as read:', err);
      return false;
    }
  }, []);

  /**
   * Mark all notifications as read
   */
  const markAllAsRead = useCallback(async (): Promise<boolean> => {
    try {
      await api.put('/api/notifications/mark-all-read');
      
      // Update local state
      setNotifications(prev => 
        prev.map(n => 
          n.status === 'unread' 
            ? { ...n, status: 'read' as const, readAt: Date.now() / 1000 }
            : n
        )
      );
      
      setUnreadCount(0);
      
      return true;
    } catch (err: any) {
      console.error('Failed to mark all notifications as read:', err);
      return false;
    }
  }, []);

  /**
   * Execute an action on a notification
   */
  const executeAction = useCallback(async (
    notificationId: string, 
    actionId: string
  ): Promise<NotificationActionResult | null> => {
    setLoading(true);
    setError(null);
    
    try {
      const response = await api.post(`/api/notifications/${notificationId}/action`, {
        actionId
      });
      
      const result = response.data as NotificationActionResult;
      
      // Update local state
      setNotifications(prev => 
        prev.map(n => 
          n.id === notificationId 
            ? { 
                ...n, 
                status: 'actioned' as const, 
                actionTaken: actionId,
                actionResult: result.message,
                actionedAt: Date.now() / 1000 
              }
            : n
        )
      );
      
      // Update unread count if it was unread
      const notification = notifications.find(n => n.id === notificationId);
      if (notification?.status === 'unread') {
        setUnreadCount(prev => Math.max(0, prev - 1));
      }
      
      return result;
    } catch (err: any) {
      const errorMessage = err.response?.data?.detail || 'Fehler bei der Ausführung der Aktion';
      setError(errorMessage);
      return null;
    } finally {
      setLoading(false);
    }
  }, [notifications]);

  /**
   * Dismiss/delete a notification
   */
  const dismissNotification = useCallback(async (notificationId: string): Promise<boolean> => {
    try {
      await api.delete(`/api/notifications/${notificationId}`);
      
      // Update local state
      const notification = notifications.find(n => n.id === notificationId);
      
      setNotifications(prev => prev.filter(n => n.id !== notificationId));
      
      // Update unread count if it was unread
      if (notification?.status === 'unread') {
        setUnreadCount(prev => Math.max(0, prev - 1));
      }
      
      return true;
    } catch (err: any) {
      console.error('Failed to dismiss notification:', err);
      return false;
    }
  }, [notifications]);

  /**
   * Start polling for new notifications
   */
  const startPolling = useCallback((intervalMs: number = 30000) => {
    // Clear any existing interval
    if (pollingIntervalRef.current) {
      clearInterval(pollingIntervalRef.current);
    }
    
    // Fetch immediately
    fetchUnreadCount();
    
    // Set up polling
    pollingIntervalRef.current = setInterval(() => {
      fetchUnreadCount();
    }, intervalMs);
  }, [fetchUnreadCount]);

  /**
   * Stop polling
   */
  const stopPolling = useCallback(() => {
    if (pollingIntervalRef.current) {
      clearInterval(pollingIntervalRef.current);
      pollingIntervalRef.current = null;
    }
  }, []);

  // Cleanup on unmount
  useEffect(() => {
    return () => {
      if (pollingIntervalRef.current) {
        clearInterval(pollingIntervalRef.current);
      }
    };
  }, []);

  return {
    notifications,
    unreadCount,
    loading,
    error,
    fetchNotifications,
    fetchUnreadCount,
    markAsRead,
    markAllAsRead,
    executeAction,
    dismissNotification,
    startPolling,
    stopPolling
  };
}

export default useNotifications;
