import React from 'react';
import { useKeyboardNavigationActivity } from '../contexts/KeyboardNavigationContext';

export type KeyboardShortcut = {
  keys: string;
  description: string;
};

const DEFAULT_SHORTCUTS: KeyboardShortcut[] = [
  { keys: '↑ / ↓', description: 'Select previous or next item' },
  { keys: 'PageUp / PageDown', description: 'Move selection by half a page' },
  { keys: 'Home / End', description: 'Jump to first or last item' },
  { keys: 'Esc', description: 'Clear current selection' },
  { keys: 'F1 or ?', description: 'Show keyboard controls' },
];

type UseKeyboardListNavigationOptions = {
  itemCount: number;
  selectedIndex: number | null;
  onSelectIndex: (index: number | null) => void;
  scrollContainerRef: React.RefObject<HTMLElement | null>;
  rowSelector?: string;
  enabled?: boolean;
  shortcuts?: KeyboardShortcut[];
};

const isTypingTarget = (target: EventTarget | null): boolean => {
  if (!(target instanceof HTMLElement)) {
    return false;
  }

  const tag = target.tagName.toLowerCase();
  return target.isContentEditable || tag === 'input' || tag === 'textarea' || tag === 'select';
};

export const useKeyboardListNavigation = ({
  itemCount,
  selectedIndex,
  onSelectIndex,
  scrollContainerRef,
  rowSelector = '[data-nav-item="true"]',
  enabled = true,
  shortcuts = DEFAULT_SHORTCUTS,
}: UseKeyboardListNavigationOptions) => {
  const [showShortcuts, setShowShortcuts] = React.useState(false);
  const { activateKeyboardNavigation, deactivateKeyboardNavigation } = useKeyboardNavigationActivity();

  React.useEffect(() => {
    if (!enabled) {
      return;
    }

    activateKeyboardNavigation();
    return () => {
      deactivateKeyboardNavigation();
    };
  }, [activateKeyboardNavigation, deactivateKeyboardNavigation, enabled]);

  const scrollToIndex = React.useCallback((index: number) => {
    const container = scrollContainerRef.current;
    if (!container) {
      return;
    }

    const rows = container.querySelectorAll<HTMLElement>(rowSelector);
    const row = rows[index];
    if (row) {
      row.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
    }
  }, [rowSelector, scrollContainerRef]);

  const getPageStep = React.useCallback((): number => {
    const container = scrollContainerRef.current;
    if (!container) {
      return 10;
    }

    const firstRow = container.querySelector<HTMLElement>(rowSelector);
    if (!firstRow || firstRow.offsetHeight <= 0) {
      return 10;
    }

    return Math.max(1, Math.floor((container.clientHeight / 2) / firstRow.offsetHeight));
  }, [rowSelector, scrollContainerRef]);

  React.useEffect(() => {
    if (!enabled) {
      return;
    }

    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.ctrlKey || event.metaKey || event.altKey) {
        return;
      }

      const isQuestionMark = event.key === '?' || (event.key === '/' && event.shiftKey);
      if (event.key === 'F1' || isQuestionMark) {
        event.preventDefault();
        setShowShortcuts(true);
        return;
      }

      if (isTypingTarget(event.target) || itemCount === 0) {
        return;
      }

      if (event.key === 'Escape') {
        event.preventDefault();
        onSelectIndex(null);
        return;
      }

      const selectAndScroll = (nextIndex: number) => {
        const bounded = Math.max(0, Math.min(nextIndex, itemCount - 1));
        onSelectIndex(bounded);
        scrollToIndex(bounded);
      };

      if (event.key === 'ArrowDown') {
        event.preventDefault();
        selectAndScroll(selectedIndex === null ? 0 : selectedIndex + 1);
        return;
      }

      if (event.key === 'ArrowUp') {
        event.preventDefault();
        selectAndScroll(selectedIndex === null ? 0 : selectedIndex - 1);
        return;
      }

      if (event.key === 'PageDown') {
        event.preventDefault();
        const step = getPageStep();
        if (selectedIndex === null) {
          selectAndScroll(step - 1);
        } else {
          selectAndScroll(selectedIndex + step);
        }
        return;
      }

      if (event.key === 'PageUp') {
        event.preventDefault();
        const step = getPageStep();
        if (selectedIndex === null) {
          selectAndScroll(0);
        } else {
          selectAndScroll(selectedIndex - step);
        }
        return;
      }

      if (event.key === 'Home') {
        event.preventDefault();
        selectAndScroll(0);
        return;
      }

      if (event.key === 'End') {
        event.preventDefault();
        selectAndScroll(itemCount - 1);
      }
    };

    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [enabled, getPageStep, itemCount, onSelectIndex, scrollToIndex, selectedIndex]);

  return {
    showShortcuts,
    setShowShortcuts,
    shortcuts,
  };
};

export const defaultKeyboardShortcuts = DEFAULT_SHORTCUTS;
