/**
 * useCohortSelection — R6UX-001 / R6UXS-002
 *
 * Shared cohort-selection primitive for every Recovery-Run surface.
 * Owns all bulk-selection state:
 *   - per-page checkbox state (selectedIds Set, string public_ids)
 *   - "select all matching" (allMatchingSelected) for whole-cohort mode
 *   - derived helpers: allPageSelected, somePageSelected, effectiveCount
 *
 * Design intent: pages adopt this hook in Waves 2-3; do not couple to any
 * specific page's filter shape here. Consumers pass pageIds + totalCount.
 *
 * Mirrors the semantics of useContentInventorySelection (F5ARCH-007) so
 * pages can adopt with a near-drop-in swap.
 */
import { useState } from 'react';

export interface UseCohortSelectionOptions {
  /** IDs visible on the current page (string public_ids). */
  pageIds: string[];
  /** Server-reported total for the current filter cohort (all pages). */
  totalCount: number;
}

export interface UseCohortSelectionReturn {
  /** Currently selected item IDs (may span pages). */
  selectedIds: Set<string>;
  /** True when the entire filter cohort (all pages) is selected. */
  allMatchingSelected: boolean;
  /** True when every item on the current page is selected. */
  allPageSelected: boolean;
  /** True when some (but not all) items on the current page are selected. */
  somePageSelected: boolean;
  /**
   * The count the bulk-action bar should use:
   * totalCount when allMatchingSelected, otherwise selectedIds.size.
   */
  effectiveCount: number;

  /** Toggle a single row's selection. Clears allMatchingSelected on deselect. */
  toggleRow: (id: string) => void;
  /**
   * Toggle all items on the current page.
   * All selected → deselect all (clears cohort selection).
   * Some/none selected → select all on page (does NOT set allMatchingSelected).
   */
  togglePageAll: () => void;
  /** Extend selection to the entire filter cohort (all pages). */
  selectAllMatching: () => void;
  /** Reset all selection state. */
  clearSelection: () => void;
  /**
   * Pre-select a single item before opening the batch modal.
   * Used by per-row action buttons.
   */
  selectSingle: (id: string) => void;
  /**
   * Clear selection after a successful batch dispatch.
   * Prevents duplicate-dispatch traps.
   */
  onDispatched: () => void;
}

export function useCohortSelection({
  pageIds,
  totalCount,
}: UseCohortSelectionOptions): UseCohortSelectionReturn {
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
  // null = page-only selection; true = whole cohort selected
  const [allMatchingSelected, setAllMatchingSelected] = useState(false);

  const allPageSelected =
    pageIds.length > 0 && pageIds.every((id) => selectedIds.has(id));
  const somePageSelected =
    pageIds.some((id) => selectedIds.has(id)) && !allPageSelected;

  const effectiveCount = allMatchingSelected ? totalCount : selectedIds.size;

  const toggleRow = (id: string) => {
    // FND-001: when allMatchingSelected is true, ANY row toggle is a deselect gesture.
    // FND-006: setAllMatchingSelected called as a sibling, not inside the updater.
    const isCurrentlySelected = allMatchingSelected || selectedIds.has(id);
    if (isCurrentlySelected) {
      // Deselecting — exit cohort mode, remove the specific row.
      setAllMatchingSelected(false);
      setSelectedIds((prev) => {
        const next = new Set(prev);
        next.delete(id);
        return next;
      });
    } else {
      setSelectedIds((prev) => {
        const next = new Set(prev);
        next.add(id);
        return next;
      });
    }
  };

  const togglePageAll = () => {
    // FND-001: treat allMatchingSelected as "the whole page is selected" so
    // clicking a checked page checkbox always exits cohort mode and deselects,
    // regardless of whether this page's ids are in selectedIds.
    const pageIsEffectivelySelected = allMatchingSelected || allPageSelected;
    if (pageIsEffectivelySelected) {
      // Deselect page — also clears cohort selection.
      setAllMatchingSelected(false);
      setSelectedIds((prev) => {
        const next = new Set(prev);
        pageIds.forEach((id) => next.delete(id));
        return next;
      });
    } else {
      setSelectedIds((prev) => {
        const next = new Set(prev);
        pageIds.forEach((id) => next.add(id));
        return next;
      });
    }
  };

  const selectAllMatching = () => {
    setAllMatchingSelected(true);
    // Ensure all page rows are checked too so the UI is coherent.
    setSelectedIds((prev) => {
      const next = new Set(prev);
      pageIds.forEach((id) => next.add(id));
      return next;
    });
  };

  const clearSelection = () => {
    setSelectedIds(new Set());
    setAllMatchingSelected(false);
  };

  const selectSingle = (id: string) => {
    setSelectedIds(new Set([id]));
    setAllMatchingSelected(false);
  };

  const onDispatched = () => {
    setSelectedIds(new Set());
    setAllMatchingSelected(false);
  };

  return {
    selectedIds,
    allMatchingSelected,
    allPageSelected,
    somePageSelected,
    effectiveCount,
    toggleRow,
    togglePageAll,
    selectAllMatching,
    clearSelection,
    selectSingle,
    onDispatched,
  };
}
