import React, { useEffect, useCallback, useRef, useState } from 'react';

interface UseKeyboardNavOptions {
  onArrowUp?: () => void;
  onArrowDown?: () => void;
  onArrowLeft?: () => void;
  onArrowRight?: () => void;
  onEnter?: () => void;
  onEscape?: () => void;
  onTab?: () => void;
  onShiftTab?: () => void;
  onSpace?: () => void;
  onHome?: () => void;
  onEnd?: () => void;
  onPageUp?: () => void;
  onPageDown?: () => void;
  onCtrlEnter?: () => void;
  disabled?: boolean;
}

export const useKeyboardNavigation = (options: UseKeyboardNavOptions, deps: React.DependencyList) => {
  const optionsRef = useRef(options);
  optionsRef.current = options;

  useEffect(() => {
    if (optionsRef.current.disabled) return;

    const handleKeyDown = (e: KeyboardEvent) => {
      const opts = optionsRef.current;
      
      // Handle Ctrl+Enter separately
      if (e.key === 'Enter' && e.ctrlKey) {
        if (opts.onCtrlEnter) {
          e.preventDefault();
          opts.onCtrlEnter();
        }
        return;
      }

      switch (e.key) {
        case 'ArrowUp':
          if (opts.onArrowUp) {
            e.preventDefault();
            opts.onArrowUp();
          }
          break;
        case 'ArrowDown':
          if (opts.onArrowDown) {
            e.preventDefault();
            opts.onArrowDown();
          }
          break;
        case 'ArrowLeft':
          if (opts.onArrowLeft) {
            e.preventDefault();
            opts.onArrowLeft();
          }
          break;
        case 'ArrowRight':
          if (opts.onArrowRight) {
            e.preventDefault();
            opts.onArrowRight();
          }
          break;
        case 'Enter':
          if (opts.onEnter) {
            e.preventDefault();
            opts.onEnter();
          }
          break;
        case 'Escape':
          if (opts.onEscape) {
            e.preventDefault();
            opts.onEscape();
          }
          break;
        case 'Tab':
          if (e.shiftKey && opts.onShiftTab) {
            e.preventDefault();
            opts.onShiftTab();
          } else if (!e.shiftKey && opts.onTab) {
            e.preventDefault();
            opts.onTab();
          }
          break;
        case ' ':
          if (opts.onSpace) {
            e.preventDefault();
            opts.onSpace();
          }
          break;
        case 'Home':
          if (opts.onHome) {
            e.preventDefault();
            opts.onHome();
          }
          break;
        case 'End':
          if (opts.onEnd) {
            e.preventDefault();
            opts.onEnd();
          }
          break;
        case 'PageUp':
          if (opts.onPageUp) {
            e.preventDefault();
            opts.onPageUp();
          }
          break;
        case 'PageDown':
          if (opts.onPageDown) {
            e.preventDefault();
            opts.onPageDown();
          }
          break;
      }
    };

    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, deps);
};

export const useFocusableList = <T extends HTMLElement>(
  itemCount: number,
  options: {
    onSelect?: (index: number) => void;
    onEscape?: () => void;
    orientation?: 'horizontal' | 'vertical';
    wrap?: boolean;
  } = {}
) => {
  const [focusedIndex, setFocusedIndex] = useState(-1);
  const itemRefs = useRef<(T | null)[]>([]);
  const { onSelect, onEscape, orientation = 'vertical', wrap = true } = options;

  const focusItem = useCallback((index: number) => {
    if (index < 0 || index >= itemCount) return;
    setFocusedIndex(index);
    itemRefs.current[index]?.focus();
    itemRefs.current[index]?.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
  }, [itemCount]);

  const handleArrowNext = useCallback(() => {
    const nextIndex = focusedIndex + 1;
    if (nextIndex < itemCount) {
      focusItem(nextIndex);
    } else if (wrap) {
      focusItem(0);
    }
  }, [focusedIndex, itemCount, wrap, focusItem]);

  const handleArrowPrev = useCallback(() => {
    const prevIndex = focusedIndex - 1;
    if (prevIndex >= 0) {
      focusItem(prevIndex);
    } else if (wrap) {
      focusItem(itemCount - 1);
    }
  }, [focusedIndex, itemCount, wrap, focusItem]);

  const handleEnter = useCallback(() => {
    if (focusedIndex >= 0 && onSelect) {
      onSelect(focusedIndex);
    }
  }, [focusedIndex, onSelect]);

  const handleHome = useCallback(() => {
    focusItem(0);
  }, [focusItem]);

  const handleEnd = useCallback(() => {
    focusItem(itemCount - 1);
  }, [focusItem, itemCount]);

  const setItemRef = useCallback((index: number) => (el: T | null) => {
    itemRefs.current[index] = el;
  }, []);

  useKeyboardNavigation({
    [orientation === 'vertical' ? 'onArrowDown' : 'onArrowRight']: handleArrowNext,
    [orientation === 'vertical' ? 'onArrowUp' : 'onArrowLeft']: handleArrowPrev,
    onEnter: handleEnter,
    onEscape,
    onHome: handleHome,
    onEnd: handleEnd,
  }, [handleArrowNext, handleArrowPrev, handleEnter, onEscape, handleHome, handleEnd]);

  return {
    focusedIndex,
    setFocusedIndex,
    focusItem,
    setItemRef,
    itemRefs,
  };
};
