import { useCallback, useRef } from 'react';

/**
 * Hook to fix scrolling issues in PrimeReact AutoComplete dropdown panels.
 * 
 * Fixes two issues:
 * 1. Mouse wheel scrolling not working properly within the dropdown
 * 2. Keyboard navigation (arrow keys) not scrolling the highlighted item into view
 * 
 * Usage:
 * ```tsx
 * const { attachScrollFix, cleanupScrollFix } = useAutoCompleteScrollFix();
 * 
 * <AutoComplete
 *   onShow={attachScrollFix}
 *   onHide={cleanupScrollFix}
 *   ...
 * />
 * ```
 */
export function useAutoCompleteScrollFix(maxHeight = '200px') {
  const observerRef = useRef<MutationObserver | null>(null);
  const wheelHandlerRef = useRef<((e: WheelEvent) => void) | null>(null);
  const itemsRef = useRef<HTMLElement | null>(null);

  const cleanupScrollFix = useCallback(() => {
    if (observerRef.current) {
      observerRef.current.disconnect();
      observerRef.current = null;
    }
    if (itemsRef.current && wheelHandlerRef.current) {
      itemsRef.current.removeEventListener('wheel', wheelHandlerRef.current as EventListener);
    }
    wheelHandlerRef.current = null;
    itemsRef.current = null;
  }, []);

  const attachScrollFix = useCallback(() => {
    // Clean up any existing handlers first
    cleanupScrollFix();

    setTimeout(() => {
      const panel = document.querySelector('.p-autocomplete-panel');
      const items = panel?.querySelector('.p-autocomplete-items') as HTMLElement | null;

      if (!items) return;

      itemsRef.current = items;

      // Apply scrollable styles
      items.style.maxHeight = maxHeight;
      items.style.overflowY = 'auto';
      items.style.overscrollBehavior = 'contain';

      // Mouse wheel scroll handler - prevent page scroll when at boundaries
      const wheelHandler = (e: WheelEvent) => {
        const delta = e.deltaY;
        const atTop = items.scrollTop === 0;
        const atBottom = items.scrollTop + items.clientHeight >= items.scrollHeight;

        if ((delta < 0 && atTop) || (delta > 0 && atBottom)) {
          e.preventDefault();
        } else {
          e.stopPropagation();
        }
      };

      wheelHandlerRef.current = wheelHandler;
      items.addEventListener('wheel', wheelHandler, { passive: false });

      // MutationObserver to watch for highlighted item changes (keyboard navigation)
      // This ensures the highlighted item scrolls into view when using arrow keys
      const observer = new MutationObserver((mutations) => {
        for (const mutation of mutations) {
          if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
            const target = mutation.target as HTMLElement;
            if (target.classList.contains('p-highlight')) {
              // Scroll the highlighted item into view
              target.scrollIntoView({
                block: 'nearest',
                behavior: 'smooth'
              });
              break;
            }
          }
        }
      });

      // Observe all autocomplete items for class changes
      const allItems = items.querySelectorAll('.p-autocomplete-item');
      allItems.forEach((item) => {
        observer.observe(item, { attributes: true, attributeFilter: ['class'] });
      });

      observerRef.current = observer;
    }, 0);
  }, [maxHeight, cleanupScrollFix]);

  return { attachScrollFix, cleanupScrollFix };
}

/**
 * Standalone function for components that don't use hooks (e.g., in event handlers).
 * Returns a cleanup function that should be called when the panel hides.
 */
export function attachAutoCompleteScrollFix(maxHeight = '200px'): () => void {
  let observer: MutationObserver | null = null;
  let wheelHandler: ((e: WheelEvent) => void) | null = null;
  let items: HTMLElement | null = null;

  setTimeout(() => {
    const panel = document.querySelector('.p-autocomplete-panel');
    items = panel?.querySelector('.p-autocomplete-items') as HTMLElement | null;

    if (!items) return;

    // Apply scrollable styles
    items.style.maxHeight = maxHeight;
    items.style.overflowY = 'auto';
    items.style.overscrollBehavior = 'contain';

    // Mouse wheel scroll handler
    wheelHandler = (e: WheelEvent) => {
      const delta = e.deltaY;
      const atTop = items!.scrollTop === 0;
      const atBottom = items!.scrollTop + items!.clientHeight >= items!.scrollHeight;

      if ((delta < 0 && atTop) || (delta > 0 && atBottom)) {
        e.preventDefault();
      } else {
        e.stopPropagation();
      }
    };

    items.addEventListener('wheel', wheelHandler, { passive: false });

    // MutationObserver for keyboard navigation scroll
    observer = new MutationObserver((mutations) => {
      for (const mutation of mutations) {
        if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
          const target = mutation.target as HTMLElement;
          if (target.classList.contains('p-highlight')) {
            target.scrollIntoView({
              block: 'nearest',
              behavior: 'smooth'
            });
            break;
          }
        }
      }
    });

    const allItems = items.querySelectorAll('.p-autocomplete-item');
    allItems.forEach((item) => {
      observer!.observe(item, { attributes: true, attributeFilter: ['class'] });
    });
  }, 0);

  // Return cleanup function
  return () => {
    if (observer) {
      observer.disconnect();
    }
    if (items && wheelHandler) {
      items.removeEventListener('wheel', wheelHandler as EventListener);
    }
  };
}
