/**
 * useOutsideClick Hook
 *
 * Detects clicks outside specified elements to clear selection.
 * Used in constructor.tsx to deselect elements when clicking outside.
 */

import { useEffect, useCallback, RefObject } from 'react';

interface UseOutsideClickOptions {
  /** Ref to the element whose outside clicks should be detected */
  containerRef: RefObject<HTMLElement | null>;
  /** Additional refs to ignore (clicking these won't trigger onOutsideClick) */
  ignoreRefs?: RefObject<HTMLElement | null>[];
  /** Data attribute to check on clicked elements (if present, won't trigger) */
  ignoreDataAttribute?: string;
  /** Current selected value to check (e.g., element ID) */
  selectedValue?: string;
  /** Callback when click outside is detected */
  onOutsideClick: () => void;
  /** Whether the hook is active */
  enabled?: boolean;
}

/**
 * Hook to detect clicks outside a container element.
 * Useful for closing panels, deselecting elements, etc.
 *
 * @example
 * useOutsideClick({
 *   containerRef: panelRef,
 *   ignoreRefs: [buttonRef],
 *   onOutsideClick: () => setSelectedId(''),
 *   enabled: !!selectedId,
 * });
 */
export function useOutsideClick({
  containerRef,
  ignoreRefs = [],
  ignoreDataAttribute,
  selectedValue,
  onOutsideClick,
  enabled = true,
}: UseOutsideClickOptions): void {
  const handleMouseDown = useCallback(
    (event: MouseEvent) => {
      const target = event.target as HTMLElement | null;
      if (!target) return;

      // Check if click is inside the container
      if (containerRef.current?.contains(target)) return;

      // Check if click is inside any ignored refs
      for (const ref of ignoreRefs) {
        if (ref.current?.contains(target)) return;
      }

      // Check for data attribute on clicked element or ancestors
      if (ignoreDataAttribute) {
        const clickedElement = target.closest(`[${ignoreDataAttribute}]`);
        if (clickedElement) {
          const attributeValue =
            clickedElement.getAttribute(ignoreDataAttribute);
          // If selected value matches clicked element's attribute, don't trigger
          if (selectedValue && attributeValue === selectedValue) return;
        }
      }

      onOutsideClick();
    },
    [
      containerRef,
      ignoreRefs,
      ignoreDataAttribute,
      selectedValue,
      onOutsideClick,
    ],
  );

  useEffect(() => {
    if (!enabled) return;

    window.addEventListener('mousedown', handleMouseDown);
    return () => window.removeEventListener('mousedown', handleMouseDown);
  }, [enabled, handleMouseDown]);
}

export default useOutsideClick;
