import { useEffect, useState, useCallback, useRef } from 'react';
import { websocketService, PresenceUpdate, WebSocketEventCallback } from '@/lib/websocket';
import { useAuth } from '@/lib/auth/AuthContext';

/**
 * React Hook for WebSocket Connection
 *
 * Features:
 * - Automatic connection management
 * - Family room subscription
 * - Connection status
 * - Presence indicators
 */

export function useWebSocket() {
  const { user, token } = useAuth();
  const [isConnected, setIsConnected] = useState(false);
  const [presence, setPresence] = useState<PresenceUpdate>({ onlineUsers: [], count: 0 });
  const hasInitialized = useRef(false);

  console.log('[useWebSocket] Hook called - User:', !!user, 'Token:', !!token, 'Initialized:', hasInitialized.current);

  // Connect to WebSocket when user is authenticated
  useEffect(() => {
    console.log('[useWebSocket] useEffect triggered - User:', !!user, 'Token:', !!token, 'Initialized:', hasInitialized.current);
    if (user && token && !hasInitialized.current) {
      hasInitialized.current = true;
      const backendUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3020';
      console.log('[useWebSocket] Connecting to:', backendUrl);
      console.log('[useWebSocket] User authenticated:', !!user);
      console.log('[useWebSocket] Token available:', !!token);

      websocketService.connect({
        url: backendUrl,
        token,
      });

      // Subscribe to connection status
      const unsubscribe = websocketService.onConnectionStatusChange(setIsConnected);

      return () => {
        console.log('[useWebSocket] Disconnecting...');
        unsubscribe();
        websocketService.disconnect();
        hasInitialized.current = false;
      };
    }
  }, [user, token]);

  // Auto-join family when user is in a family
  useEffect(() => {
    const familyId = user?.families?.[0]?.familyId;
    if (isConnected && familyId) {
      console.log('[useWebSocket] Auto-joining family:', familyId);
      websocketService.joinFamily(familyId);

      return () => {
        websocketService.leaveFamily();
      };
    }
  }, [isConnected, user?.families]);

  // Subscribe to presence updates
  useEffect(() => {
    const unsubscribe = websocketService.on<PresenceUpdate>('presenceUpdate', setPresence);

    // Get initial presence when family is joined
    const unsubscribeJoined = websocketService.on('familyJoined', (data: any) => {
      if (data.onlineUsers) {
        setPresence({ onlineUsers: data.onlineUsers, count: data.onlineUsers.length });
      }
    });

    return () => {
      unsubscribe();
      unsubscribeJoined();
    };
  }, []);

  // Join a specific family room
  const joinFamily = useCallback((familyId: string) => {
    if (isConnected) {
      websocketService.joinFamily(familyId);
    }
  }, [isConnected]);

  // Leave current family room
  const leaveFamily = useCallback(() => {
    websocketService.leaveFamily();
  }, []);

  return {
    isConnected,
    presence,
    joinFamily,
    leaveFamily,
  };
}

/**
 * Hook for subscribing to specific WebSocket events
 */
export function useWebSocketEvent<T = any>(
  event: string,
  callback: WebSocketEventCallback<T>,
  dependencies: any[] = []
) {
  useEffect(() => {
    const unsubscribe = websocketService.on<T>(event, callback);
    return unsubscribe;
  }, [event, ...dependencies]); // eslint-disable-line react-hooks/exhaustive-deps
}

/**
 * Hook for real-time activity updates
 *
 * Automatically updates local state when activities are created/updated/deleted by other family members
 */
export function useRealTimeActivities(
  onActivityCreated?: (activity: any) => void,
  onActivityUpdated?: (activity: any) => void,
  onActivityDeleted?: (data: { activityId: string }) => void
) {
  useWebSocketEvent('activityCreated', (activity) => {
    console.log('[useRealTimeActivities] Activity created:', activity);
    onActivityCreated?.(activity);
  }, [onActivityCreated]);

  useWebSocketEvent('activityUpdated', (activity) => {
    console.log('[useRealTimeActivities] Activity updated:', activity);
    onActivityUpdated?.(activity);
  }, [onActivityUpdated]);

  useWebSocketEvent('activityDeleted', (data) => {
    console.log('[useRealTimeActivities] Activity deleted:', data);
    onActivityDeleted?.(data);
  }, [onActivityDeleted]);
}

/**
 * Hook for real-time child updates
 */
export function useRealTimeChildren(
  onChildAdded?: (child: any) => void,
  onChildUpdated?: (child: any) => void,
  onChildDeleted?: (data: { childId: string }) => void
) {
  useWebSocketEvent('childAdded', (child) => {
    console.log('[useRealTimeChildren] Child added:', child);
    onChildAdded?.(child);
  }, [onChildAdded]);

  useWebSocketEvent('childUpdated', (child) => {
    console.log('[useRealTimeChildren] Child updated:', child);
    onChildUpdated?.(child);
  }, [onChildUpdated]);

  useWebSocketEvent('childDeleted', (data) => {
    console.log('[useRealTimeChildren] Child deleted:', data);
    onChildDeleted?.(data);
  }, [onChildDeleted]);
}

/**
 * Hook for real-time family member updates
 */
export function useRealTimeFamilyMembers(
  onMemberAdded?: (member: any) => void,
  onMemberUpdated?: (member: any) => void,
  onMemberRemoved?: (data: { userId: string }) => void
) {
  useWebSocketEvent('memberAdded', (member) => {
    console.log('[useRealTimeFamilyMembers] Member added:', member);
    onMemberAdded?.(member);
  }, [onMemberAdded]);

  useWebSocketEvent('memberUpdated', (member) => {
    console.log('[useRealTimeFamilyMembers] Member updated:', member);
    onMemberUpdated?.(member);
  }, [onMemberUpdated]);

  useWebSocketEvent('memberRemoved', (data) => {
    console.log('[useRealTimeFamilyMembers] Member removed:', data);
    onMemberRemoved?.(data);
  }, [onMemberRemoved]);
}
