import { useEffect, useCallback } from 'react';
import { useAppStore, parseShortcut } from '@/store/app-store';

export interface KeyboardShortcut {
  key: string; // Can be simple "K" or with modifiers "Shift+N", "Cmd+K"
  action: () => void;
  description?: string;
}

/**
 * Check if the currently focused element is an input, textarea, or contenteditable element
 * or if an autocomplete/typeahead dropdown is open
 */
function isInputFocused(): boolean {
  const activeElement = document.activeElement;
  if (!activeElement) return false;

  // Check if it's a form input element
  const tagName = activeElement.tagName.toLowerCase();
  if (tagName === 'input' || tagName === 'textarea' || tagName === 'select') {
    return true;
  }

  // Check if it's a contenteditable element
  if (activeElement.getAttribute('contenteditable') === 'true') {
    return true;
  }

  // Check if it has a role of textbox or searchbox
  const role = activeElement.getAttribute('role');
  if (role === 'textbox' || role === 'searchbox' || role === 'combobox') {
    return true;
  }

  // Check if focus is inside an xterm terminal (they use a hidden textarea)
  const xtermContainer = activeElement.closest('.xterm');
  if (xtermContainer) {
    return true;
  }

  // Also check if any parent has data-terminal-container attribute
  const terminalContainer = activeElement.closest('[data-terminal-container]');
  if (terminalContainer) {
    return true;
  }

  // Check for autocomplete/typeahead dropdowns being open
  const autocompleteList = document.querySelector('[data-testid="category-autocomplete-list"]');
  if (autocompleteList) {
    return true;
  }

  // Check for any open dialogs
  const dialog = document.querySelector('[role="dialog"][data-state="open"]');
  if (dialog) {
    return true;
  }

  // Check for project picker dropdown being open
  const projectPickerDropdown = document.querySelector('[data-testid="project-picker-dropdown"]');
  if (projectPickerDropdown) {
    return true;
  }

  // Check for any open dropdown menus (Radix UI uses role="menu")
  // This prevents shortcuts from firing when user is typing in dropdown filters
  const dropdownMenu = document.querySelector('[role="menu"]');
  if (dropdownMenu) {
    return true;
  }

  return false;
}

/**
 * Convert a key character to its corresponding event.code
 * This is used for keyboard-layout independent matching in terminals
 */
function keyToCode(key: string): string {
  const upperKey = key.toUpperCase();

  // Letters A-Z map to KeyA-KeyZ
  if (/^[A-Z]$/.test(upperKey)) {
    return `Key${upperKey}`;
  }

  // Numbers 0-9 on main row map to Digit0-Digit9
  if (/^[0-9]$/.test(key)) {
    return `Digit${key}`;
  }

  // Special key mappings
  const specialMappings: Record<string, string> = {
    '`': 'Backquote',
    '~': 'Backquote',
    '-': 'Minus',
    _: 'Minus',
    '=': 'Equal',
    '+': 'Equal',
    '[': 'BracketLeft',
    '{': 'BracketLeft',
    ']': 'BracketRight',
    '}': 'BracketRight',
    '\\': 'Backslash',
    '|': 'Backslash',
    ';': 'Semicolon',
    ':': 'Semicolon',
    "'": 'Quote',
    '"': 'Quote',
    ',': 'Comma',
    '<': 'Comma',
    '.': 'Period',
    '>': 'Period',
    '/': 'Slash',
    '?': 'Slash',
    ' ': 'Space',
    Enter: 'Enter',
    Tab: 'Tab',
    Escape: 'Escape',
    Backspace: 'Backspace',
    Delete: 'Delete',
    ArrowUp: 'ArrowUp',
    ArrowDown: 'ArrowDown',
    ArrowLeft: 'ArrowLeft',
    ArrowRight: 'ArrowRight',
  };

  return specialMappings[key] || specialMappings[upperKey] || key;
}

/**
 * Check if a keyboard event matches a shortcut definition using event.code
 * This is keyboard-layout independent - useful for terminals where Alt+key
 * combinations can produce special characters with event.key
 */
export function matchesShortcutWithCode(event: KeyboardEvent, shortcutStr: string): boolean {
  const shortcut = parseShortcut(shortcutStr);
  if (!shortcut.key) return false;

  // Convert the shortcut key to event.code format
  const expectedCode = keyToCode(shortcut.key);

  // Check if the code matches
  if (event.code !== expectedCode) {
    return false;
  }

  // Check modifier keys
  const cmdCtrlPressed = event.metaKey || event.ctrlKey;
  const shiftPressed = event.shiftKey;
  const altPressed = event.altKey;

  // If shortcut requires cmdCtrl, it must be pressed
  if (shortcut.cmdCtrl && !cmdCtrlPressed) return false;
  // If shortcut doesn't require cmdCtrl, it shouldn't be pressed
  if (!shortcut.cmdCtrl && cmdCtrlPressed) return false;

  // If shortcut requires shift, it must be pressed
  if (shortcut.shift && !shiftPressed) return false;
  // If shortcut doesn't require shift, it shouldn't be pressed
  if (!shortcut.shift && shiftPressed) return false;

  // If shortcut requires alt, it must be pressed
  if (shortcut.alt && !altPressed) return false;
  // If shortcut doesn't require alt, it shouldn't be pressed
  if (!shortcut.alt && altPressed) return false;

  return true;
}

/**
 * Check if a keyboard event matches a shortcut definition
 */
function matchesShortcut(event: KeyboardEvent, shortcutStr: string): boolean {
  const shortcut = parseShortcut(shortcutStr);

  // Check if the key matches (case-insensitive)
  if (event.key.toLowerCase() !== shortcut.key.toLowerCase()) {
    return false;
  }

  // Check modifier keys
  const cmdCtrlPressed = event.metaKey || event.ctrlKey;
  const shiftPressed = event.shiftKey;
  const altPressed = event.altKey;

  // If shortcut requires cmdCtrl, it must be pressed
  if (shortcut.cmdCtrl && !cmdCtrlPressed) return false;
  // If shortcut doesn't require cmdCtrl, it shouldn't be pressed
  if (!shortcut.cmdCtrl && cmdCtrlPressed) return false;

  // If shortcut requires shift, it must be pressed
  if (shortcut.shift && !shiftPressed) return false;
  // If shortcut doesn't require shift, it shouldn't be pressed
  if (!shortcut.shift && shiftPressed) return false;

  // If shortcut requires alt, it must be pressed
  if (shortcut.alt && !altPressed) return false;
  // If shortcut doesn't require alt, it shouldn't be pressed
  if (!shortcut.alt && altPressed) return false;

  return true;
}

/**
 * Hook to manage keyboard shortcuts
 * Shortcuts won't fire when user is typing in inputs, textareas, or when dialogs are open
 * Supports modifier keys: Shift, Cmd/Ctrl, Alt/Option
 */
export function useKeyboardShortcuts(shortcuts: KeyboardShortcut[]) {
  const handleKeyDown = useCallback(
    (event: KeyboardEvent) => {
      // Don't trigger shortcuts when typing in inputs
      if (isInputFocused()) {
        return;
      }

      // Find matching shortcut
      const matchingShortcut = shortcuts.find((shortcut) => matchesShortcut(event, shortcut.key));

      if (matchingShortcut) {
        event.preventDefault();
        matchingShortcut.action();
      }
    },
    [shortcuts]
  );

  useEffect(() => {
    window.addEventListener('keydown', handleKeyDown);
    return () => {
      window.removeEventListener('keydown', handleKeyDown);
    };
  }, [handleKeyDown]);
}

/**
 * Hook to get current keyboard shortcuts from store
 * This replaces the static constants and allows customization
 */
export function useKeyboardShortcutsConfig() {
  const keyboardShortcuts = useAppStore((state) => state.keyboardShortcuts);
  return keyboardShortcuts;
}
