'use client';

import { useEffect, useRef } from 'react';
import { useQueryClient } from '@tanstack/react-query';

import { useSocket } from '@/providers/socket-provider';
import { subscribeRealtimeInvalidations, type EventMap } from '@/hooks/realtime-invalidation-core';

// Re-export for convenience so callers don't need to know about the split.
export type { EventMap, SocketLike } from '@/hooks/realtime-invalidation-core';

/**
 * Subscribes to socket events and invalidates React Query caches.
 *
 * Safe to call with an inline-literal `eventMap` - the hook only re-subscribes
 * when the SET of event keys actually changes (not when the object identity
 * changes). The latest query-key list is read at event fire-time via a ref.
 *
 * @example
 * useRealtimeInvalidation({
 *   'client:created': [['clients']],
 *   'client:updated': [['clients'], ['clients', clientId]],
 *   'client:archived': [['clients']],
 * });
 */
export function useRealtimeInvalidation(eventMap: EventMap) {
  const socket = useSocket();
  const queryClient = useQueryClient();

  // Stash the latest map in a ref so handlers always see fresh queryKeys
  // without re-subscribing. Writing to ref.current during render trips
  // the React Compiler purity rules; the equivalent layout-effect
  // wiring runs synchronously after commit and is Compiler-safe.
  const eventMapRef = useRef(eventMap);
  useEffect(() => {
    eventMapRef.current = eventMap;
  });

  // Re-subscribe ONLY when the set of event names changes. Object identity
  // of `eventMap` flips on every caller render; the joined key signature
  // doesn't.
  const eventKeysSig = Object.keys(eventMap).sort().join('|');

  useEffect(() => {
    if (!socket) return;
    // eventMapRef is intentionally not in deps - it's a ref; we only want to
    // re-run when the socket, queryClient, or the event-key SET changes.
    return subscribeRealtimeInvalidations(
      socket,
      eventKeysSig.length > 0 ? eventKeysSig.split('|') : [],
      queryClient,
      () => eventMapRef.current,
    );
  }, [socket, queryClient, eventKeysSig]);
}
