import { useState, useEffect, useCallback, useRef } from 'react';
import { notificationsApi, Notification } from '@/lib/api/notifications';

const POLL_INTERVAL = 30000; // 30 seconds
const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes

interface UseNotificationsReturn {
  notifications: Notification[];
  unreadCount: number;
  loading: boolean;
  error: string | null;
  refresh: () => Promise<void>;
  markAsRead: (notificationId: string) => Promise<void>;
  markAllAsRead: () => Promise<void>;
  dismiss: (notificationId: string) => Promise<void>;
}

export function useNotifications(options?: {
  limit?: number;
  autoRefresh?: boolean;
}): UseNotificationsReturn {
  const { limit = 10, autoRefresh = true } = options || {};

  const [notifications, setNotifications] = useState<Notification[]>([]);
  const [unreadCount, setUnreadCount] = useState(0);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const lastFetchRef = useRef<number>(0);
  const pollIntervalRef = useRef<NodeJS.Timeout | null>(null);

  const fetchNotifications = useCallback(async (force = false) => {
    const now = Date.now();

    // Use cache if data is fresh and not forced
    if (!force && now - lastFetchRef.current < CACHE_DURATION) {
      return;
    }

    try {
      setError(null);
      const response = await notificationsApi.getNotifications({
        limit,
        offset: 0,
      });

      setNotifications(response.notifications);
      setUnreadCount(response.unreadCount);
      lastFetchRef.current = now;
    } catch (err: any) {
      console.error('❌ Failed to fetch notifications:', err);
      setError(err.response?.data?.message || 'Failed to load notifications');
    } finally {
      setLoading(false);
    }
  }, [limit]);

  const refresh = useCallback(async () => {
    setLoading(true);
    await fetchNotifications(true);
  }, [fetchNotifications]);

  const markAsRead = useCallback(async (notificationId: string) => {
    try {
      // Optimistic update
      setNotifications((prev) =>
        prev.map((n) => (n.id === notificationId ? { ...n, isRead: true, readAt: new Date().toISOString() } : n))
      );
      setUnreadCount((prev) => Math.max(0, prev - 1));

      // API call
      await notificationsApi.markAsRead(notificationId);
    } catch (err: any) {
      console.error('❌ Failed to mark notification as read:', err);
      // Revert optimistic update on error
      await refresh();
    }
  }, [refresh]);

  const markAllAsRead = useCallback(async () => {
    try {
      // Optimistic update
      setNotifications((prev) =>
        prev.map((n) => ({ ...n, isRead: true, readAt: new Date().toISOString() }))
      );
      setUnreadCount(0);

      // API call
      await notificationsApi.markAllAsRead();
    } catch (err: any) {
      console.error('❌ Failed to mark all notifications as read:', err);
      // Revert optimistic update on error
      await refresh();
    }
  }, [refresh]);

  const dismiss = useCallback(async (notificationId: string) => {
    try {
      // Optimistic update
      setNotifications((prev) => prev.filter((n) => n.id !== notificationId));
      setUnreadCount((prev) => {
        const notification = notifications.find((n) => n.id === notificationId);
        return notification && !notification.isRead ? Math.max(0, prev - 1) : prev;
      });

      // API call
      await notificationsApi.dismiss(notificationId);
    } catch (err: any) {
      console.error('❌ Failed to dismiss notification:', err);
      // Revert optimistic update on error
      await refresh();
    }
  }, [notifications, refresh]);

  // Initial fetch
  useEffect(() => {
    fetchNotifications(true);
  }, [fetchNotifications]);

  // Setup polling
  useEffect(() => {
    if (!autoRefresh) return;

    pollIntervalRef.current = setInterval(() => {
      fetchNotifications(false);
    }, POLL_INTERVAL);

    return () => {
      if (pollIntervalRef.current) {
        clearInterval(pollIntervalRef.current);
      }
    };
  }, [autoRefresh, fetchNotifications]);

  // Refresh on tab focus
  useEffect(() => {
    const handleVisibilityChange = () => {
      if (!document.hidden) {
        fetchNotifications(false);
      }
    };

    document.addEventListener('visibilitychange', handleVisibilityChange);
    return () => {
      document.removeEventListener('visibilitychange', handleVisibilityChange);
    };
  }, [fetchNotifications]);

  return {
    notifications,
    unreadCount,
    loading,
    error,
    refresh,
    markAsRead,
    markAllAsRead,
    dismiss,
  };
}
