import { 
  Directive, 
  Input, 
  Output, 
  EventEmitter, 
  HostListener, 
  OnInit, 
  OnDestroy,
  inject
} from '@angular/core';
import { DOCUMENT } from '@angular/common';

export interface KeyboardShortcut {
  key: string;
  ctrlKey?: boolean;
  metaKey?: boolean;
  altKey?: boolean;
  shiftKey?: boolean;
  preventDefault?: boolean;
  target?: string; // CSS selector for target elements
}

export interface KeyboardEvent {
  shortcut: KeyboardShortcut;
  event: globalThis.KeyboardEvent;
}

@Directive({
  selector: '[uiGlobalKeyboard]',
  standalone: true
})
export class GlobalKeyboardDirective implements OnInit, OnDestroy {
  private document = inject(DOCUMENT) as Document;

  @Input() shortcuts: KeyboardShortcut[] = [];
  @Input() enabled = true;
  @Input() ignoreInputs = true;
  @Input() ignoreContentEditable = true;

  @Output() shortcutTriggered = new EventEmitter<KeyboardEvent>();

  private boundKeydownHandler = this.handleKeydown.bind(this);

  ngOnInit(): void {
    if (this.enabled) {
      this.document.addEventListener('keydown', this.boundKeydownHandler, true);
    }
  }

  ngOnDestroy(): void {
    this.document.removeEventListener('keydown', this.boundKeydownHandler, true);
  }

  private handleKeydown(event: globalThis.KeyboardEvent): void {
    if (!this.enabled) return;

    // Skip if typing in form inputs (unless specifically disabled)
    if (this.ignoreInputs && this.isTypingInInput(event.target as Element)) {
      return;
    }

    // Skip if editing content (unless specifically disabled)
    if (this.ignoreContentEditable && this.isEditingContent(event.target as Element)) {
      return;
    }

    // Check each shortcut for a match
    for (const shortcut of this.shortcuts) {
      if (this.isShortcutMatch(event, shortcut)) {
        // Check if target element matches (if specified)
        if (shortcut.target && !this.isTargetMatch(event.target as Element, shortcut.target)) {
          continue;
        }

        // Prevent default behavior if specified
        if (shortcut.preventDefault !== false) {
          event.preventDefault();
          event.stopPropagation();
        }

        // Emit the shortcut event
        this.shortcutTriggered.emit({
          shortcut,
          event
        });

        // Stop after first match
        break;
      }
    }
  }

  private isShortcutMatch(event: globalThis.KeyboardEvent, shortcut: KeyboardShortcut): boolean {
    // Normalize key comparison (case-insensitive for letters)
    const eventKey = event.key.toLowerCase();
    const shortcutKey = shortcut.key.toLowerCase();
    
    // Handle special cases for common keys
    const keyMatch = this.normalizeKey(eventKey) === this.normalizeKey(shortcutKey);
    
    // Check modifier keys
    const ctrlMatch = (shortcut.ctrlKey || false) === event.ctrlKey;
    const metaMatch = (shortcut.metaKey || false) === event.metaKey;
    const altMatch = (shortcut.altKey || false) === event.altKey;
    const shiftMatch = (shortcut.shiftKey || false) === event.shiftKey;

    return keyMatch && ctrlMatch && metaMatch && altMatch && shiftMatch;
  }

  private normalizeKey(key: string): string {
    // Handle special key mappings
    const keyMap: { [key: string]: string } = {
      ' ': 'space',
      'arrowup': 'up',
      'arrowdown': 'down',
      'arrowleft': 'left',
      'arrowright': 'right',
      'delete': 'del',
      'escape': 'esc'
    };

    return keyMap[key.toLowerCase()] || key.toLowerCase();
  }

  private isTypingInInput(target: Element | null): boolean {
    if (!target) return false;

    const tagName = target.tagName.toLowerCase();
    const inputTypes = ['input', 'textarea', 'select'];
    
    if (inputTypes.includes(tagName)) {
      const element = target as HTMLInputElement | HTMLTextAreaElement;
      
      // Skip if it's a non-text input
      if (tagName === 'input') {
        const type = (element as HTMLInputElement).type.toLowerCase();
        const nonTextTypes = ['submit', 'reset', 'button', 'checkbox', 'radio', 'file', 'image'];
        if (nonTextTypes.includes(type)) {
          return false;
        }
      }

      // Check if element is disabled or readonly
      return !element.disabled && !element.readOnly;
    }

    return false;
  }

  private isEditingContent(target: Element | null): boolean {
    if (!target) return false;

    // Check if element or any parent has contenteditable
    let element = target as Element;
    while (element) {
      if (element.getAttribute && element.getAttribute('contenteditable') === 'true') {
        return true;
      }
      element = element.parentElement as Element;
      
      // Stop at body to avoid infinite loop
      if (!element || element.tagName.toLowerCase() === 'body') {
        break;
      }
    }

    return false;
  }

  private isTargetMatch(target: Element | null, selector: string): boolean {
    if (!target) return false;

    try {
      return target.matches(selector) || !!target.closest(selector);
    } catch (error) {
      console.warn('Invalid CSS selector in keyboard shortcut:', selector, error);
      return false;
    }
  }

  // Public API methods
  addShortcut(shortcut: KeyboardShortcut): void {
    this.shortcuts = [...this.shortcuts, shortcut];
  }

  removeShortcut(shortcut: KeyboardShortcut): void {
    this.shortcuts = this.shortcuts.filter(s => 
      s.key !== shortcut.key || 
      s.ctrlKey !== shortcut.ctrlKey || 
      s.metaKey !== shortcut.metaKey || 
      s.altKey !== shortcut.altKey || 
      s.shiftKey !== shortcut.shiftKey
    );
  }

  clearShortcuts(): void {
    this.shortcuts = [];
  }

  enable(): void {
    if (!this.enabled) {
      this.enabled = true;
      this.document.addEventListener('keydown', this.boundKeydownHandler, true);
    }
  }

  disable(): void {
    if (this.enabled) {
      this.enabled = false;
      this.document.removeEventListener('keydown', this.boundKeydownHandler, true);
    }
  }
}

// Helper function to create common shortcuts
export function createShortcuts() {
  return {
    // Command palette
    commandPalette: (): KeyboardShortcut => ({
      key: 'k',
      ctrlKey: !isMac(),
      metaKey: isMac(),
      preventDefault: true
    }),

    // Quick actions
    quickSearch: (): KeyboardShortcut => ({
      key: '/',
      preventDefault: true
    }),

    // Navigation
    goHome: (): KeyboardShortcut => ({
      key: 'h',
      ctrlKey: !isMac(),
      metaKey: isMac(),
      preventDefault: true
    }),

    goBack: (): KeyboardShortcut => ({
      key: '[',
      ctrlKey: !isMac(),
      metaKey: isMac(),
      preventDefault: true
    }),

    goForward: (): KeyboardShortcut => ({
      key: ']',
      ctrlKey: !isMac(),
      metaKey: isMac(),
      preventDefault: true
    }),

    // Common actions
    save: (): KeyboardShortcut => ({
      key: 's',
      ctrlKey: !isMac(),
      metaKey: isMac(),
      preventDefault: true
    }),

    copy: (): KeyboardShortcut => ({
      key: 'c',
      ctrlKey: !isMac(),
      metaKey: isMac(),
      preventDefault: false // Let browser handle copy
    }),

    paste: (): KeyboardShortcut => ({
      key: 'v',
      ctrlKey: !isMac(),
      metaKey: isMac(),
      preventDefault: false // Let browser handle paste
    }),

    // Custom shortcut builder
    create: (key: string, modifiers: {
      ctrl?: boolean;
      meta?: boolean;
      alt?: boolean;
      shift?: boolean;
      preventDefault?: boolean;
      target?: string;
    } = {}): KeyboardShortcut => ({
      key,
      ctrlKey: modifiers.ctrl,
      metaKey: modifiers.meta,
      altKey: modifiers.alt,
      shiftKey: modifiers.shift,
      preventDefault: modifiers.preventDefault ?? true,
      target: modifiers.target
    })
  };
}

// Platform detection helper
function isMac(): boolean {
  return typeof navigator !== 'undefined' && navigator.platform.toUpperCase().indexOf('MAC') >= 0;
}