'use client';

import { useEffect, useRef } from 'react';
import { io, type Socket } from 'socket.io-client';
import { useAuthStore } from '@/lib/auth-store';
import type { NotificationDto } from '@/lib/notifications-api';
import { useNotificationsStore } from '@/lib/notifications-store';

const SOCKET_URL = process.env['NEXT_PUBLIC_API_URL']?.replace('/api/v1', '') || 'http://localhost:3001';

/**
 * Hook that manages the Socket.IO connection for real-time notifications.
 *
 * - Connects when user is authenticated
 * - Listens for `notification:new` events
 * - Auto-reconnects on disconnect
 * - Disconnects on logout
 */
export function useSocketNotifications() {
  const socketRef = useRef<Socket | null>(null);
  const isAuthenticated = useAuthStore((s) => s.isAuthenticated);
  const { addNotification, incrementUnread, fetchUnreadCount } =
    useNotificationsStore();

  useEffect(() => {
    if (!isAuthenticated) {
      // Disconnect if user logs out
      if (socketRef.current) {
        socketRef.current.disconnect();
        socketRef.current = null;
      }
      return;
    }

    // Don't create duplicate connections
    if (socketRef.current?.connected) return;

    const socket = io(SOCKET_URL, {
      path: '/socket.io',
      withCredentials: true, // Send httpOnly auth cookies
      transports: ['websocket', 'polling'],
      reconnection: true,
      reconnectionAttempts: Infinity,
      reconnectionDelay: 1000,
      reconnectionDelayMax: 10000,
      autoConnect: true,
    });

    socket.on('connect', () => {
      // Fetch unread count on (re)connect to sync state
      fetchUnreadCount();
    });

    socket.on('notification:new', (data: NotificationDto) => {
      addNotification(data);
      incrementUnread();
    });

    socket.on('disconnect', (reason) => {
      // Socket.IO auto-reconnects for transport errors.
      // Only manual disconnects ('io client disconnect') need explicit reconnect.
      if (reason === 'io server disconnect') {
        socket.connect();
      }
    });

    socketRef.current = socket;

    return () => {
      socket.disconnect();
      socketRef.current = null;
    };
  }, [isAuthenticated, addNotification, incrementUnread, fetchUnreadCount]);
}
