/**
 * @ai-summary Hook for managing bulk selection state across paginated data
 * @ai-context Supports individual toggle, select all, and reset operations
 */

import { useState, useCallback, useMemo } from 'react';

/**
 * Options for bulk selection hook
 */
interface UseBulkSelectionOptions<T> {
  items: T[];
  keyExtractor?: (item: T) => string;
}

/**
 * Return type for bulk selection hook
 */
interface UseBulkSelectionReturn<T> {
  selected: Set<string>;
  toggleItem: (id: string) => void;
  toggleAll: (items: T[]) => void;
  isSelected: (id: string) => boolean;
  reset: () => void;
  count: number;
  selectedItems: T[];
}

/**
 * Custom hook for managing bulk selection state
 * Supports selection across pagination boundaries
 *
 * @example
 * ```typescript
 * const { selected, toggleItem, toggleAll, reset, count } = useBulkSelection({ items: data });
 * ```
 */
export function useBulkSelection<T extends { id: string }>(
  options: UseBulkSelectionOptions<T>
): UseBulkSelectionReturn<T> {
  const { items, keyExtractor = (item: T) => item.id } = options;

  const [selected, setSelected] = useState<Set<string>>(new Set());

  /**
   * Toggle individual item selection
   */
  const toggleItem = useCallback((id: string) => {
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(id)) {
        next.delete(id);
      } else {
        next.add(id);
      }
      return next;
    });
  }, []);

  /**
   * Toggle all items - if all are selected, deselect all; otherwise select all
   * This supports "Select All" across pagination
   */
  const toggleAll = useCallback((itemsToToggle: T[]) => {
    setSelected((prev) => {
      const itemIds = itemsToToggle.map(keyExtractor);
      const allSelected = itemIds.every((id) => prev.has(id));

      if (allSelected) {
        // Deselect all items
        const next = new Set(prev);
        itemIds.forEach((id) => next.delete(id));
        return next;
      } else {
        // Select all items
        const next = new Set(prev);
        itemIds.forEach((id) => next.add(id));
        return next;
      }
    });
  }, [keyExtractor]);

  /**
   * Check if item is selected
   */
  const isSelected = useCallback(
    (id: string) => selected.has(id),
    [selected]
  );

  /**
   * Clear all selections
   */
  const reset = useCallback(() => {
    setSelected(new Set());
  }, []);

  /**
   * Get array of selected items from current items list
   */
  const selectedItems = useMemo(() => {
    return items.filter((item) => selected.has(keyExtractor(item)));
  }, [items, selected, keyExtractor]);

  return {
    selected,
    toggleItem,
    toggleAll,
    isSelected,
    reset,
    count: selected.size,
    selectedItems,
  };
}
