'use client';

/**
 * Global keyboard shortcut registration system.
 * Registers keyboard shortcuts with scope awareness.
 *
 * Usage:
 *   useKeyboardShortcut({
 *     key: 'k',
 *     meta: true,
 *     scope: 'global',
 *     action: () => openCommandPalette(),
 *   });
 *
 * Scopes: 'global' > 'page' > 'component'
 * Multiple shortcuts can be registered; global shortcuts work everywhere.
 */

import { useEffect, useRef } from 'react';

export type ShortcutScope = 'global' | 'page' | 'component';

interface Shortcut {
  key: string;
  ctrl?: boolean;
  meta?: boolean;
  shift?: boolean;
  alt?: boolean;
  scope: ShortcutScope;
  action: () => void;
  description?: string;
}

const registeredShortcuts: Shortcut[] = [];

/** Normalize a key string to lowercase */
function normalizeKey(key: string): string {
  return key.toLowerCase().replace(/\s+/g, '');
}

/** Check if an event matches a shortcut */
function matchesShortcut(event: KeyboardEvent, shortcut: Shortcut): boolean {
  const keyMatch = normalizeKey(event.key) === normalizeKey(shortcut.key);
  const ctrlMatch = !!shortcut.ctrl === (event.ctrlKey || event.metaKey); // treat ctrl/meta as equivalent
  const shiftMatch = !!shortcut.shift === event.shiftKey;
  const altMatch = !!shortcut.alt === event.altKey;
  return keyMatch && ctrlMatch && shiftMatch && altMatch;
}

/** Sort shortcuts by priority: global first, then page, then component */
function sortShortcuts(shortcuts: Shortcut[]): Shortcut[] {
  const order = { global: 0, page: 1, component: 2 } as const;
  return [...shortcuts].sort((a, b) => order[a.scope] - order[b.scope]);
}

function handleKeyDown(event: KeyboardEvent) {
  // Don't fire shortcuts when typing in inputs/textareas (unless explicitly allowed)
  const target = event.target as HTMLElement;
  const isEditing = target.tagName === 'INPUT' ||
    target.tagName === 'TEXTAREA' ||
    target.isContentEditable;

  for (const shortcut of sortShortcuts(registeredShortcuts)) {
    if (isEditing && shortcut.scope === 'global') {
      // Global shortcuts still fire in inputs for accessibility (e.g. Cmd+K)
      // but let components decide by checking the shortcut
    }
    if (matchesShortcut(event, shortcut)) {
      event.preventDefault();
      shortcut.action();
      return;
    }
  }
}

export interface UseKeyboardShortcutOptions {
  key: string;
  ctrl?: boolean;
  meta?: boolean;
  shift?: boolean;
  alt?: boolean;
  scope?: ShortcutScope;
  action: () => void;
  description?: string;
  /** If true, fires even when typing in inputs. Default: false for 'component', true for 'global' */
  forceInInput?: boolean;
}

/**
 * Register a keyboard shortcut. Returns a cleanup function.
 * Call this inside a useEffect (or component body, since it auto-cleans on unmount).
 */
export function useKeyboardShortcut({
  key,
  ctrl,
  meta,
  shift,
  alt,
  scope = 'component',
  action,
  description,
}: UseKeyboardShortcutOptions): () => void {
  const shortcutRef = useRef<Shortcut>({
    key,
    ctrl,
    meta,
    shift,
    alt,
    scope,
    action,
    description,
  });

  useEffect(() => {
    // Deduplicate: remove any existing shortcut with the same key+scope
    const idx = registeredShortcuts.findIndex(
      (s) =>
        normalizeKey(s.key) === normalizeKey(key) &&
        s.scope === scope,
    );
    if (idx !== -1) {
      registeredShortcuts.splice(idx, 1);
    }
    registeredShortcuts.push(shortcutRef.current);

    return () => {
      const i = registeredShortcuts.indexOf(shortcutRef.current);
      if (i !== -1) registeredShortcuts.splice(i, 1);
    };
  }, [key, scope]); // eslint-disable-line react-hooks/exhaustive-deps

  return () => {
    const i = registeredShortcuts.indexOf(shortcutRef.current);
    if (i !== -1) registeredShortcuts.splice(i, 1);
  };
}

/** Get all registered shortcuts (for help sheet display) */
export function getRegisteredShortcuts(scope?: ShortcutScope): Shortcut[] {
  if (scope) return registeredShortcuts.filter((s) => s.scope === scope);
  return [...registeredShortcuts];
}

// Initialize global listener once
let globalListenerRegistered = false;

export function registerGlobalKeyboardListener(): void {
  if (globalListenerRegistered) return;
  window.addEventListener('keydown', handleKeyDown);
  globalListenerRegistered = true;
}

export function unregisterGlobalKeyboardListener(): void {
  if (!globalListenerRegistered) return;
  window.removeEventListener('keydown', handleKeyDown);
  globalListenerRegistered = false;
}

/** Format a shortcut for display (e.g. "Cmd+K", "Ctrl+Shift+S") */
export function formatShortcut(options: {
  key: string;
  ctrl?: boolean;
  meta?: boolean;
  shift?: boolean;
  alt?: boolean;
}): string {
  const parts: string[] = [];
  if (options.meta) parts.push(navigator.platform.includes('Mac') ? '⌘' : 'Cmd');
  if (options.ctrl) parts.push('Ctrl');
  if (options.alt) parts.push(navigator.platform.includes('Mac') ? '⌥' : 'Alt');
  if (options.shift) parts.push('⇧');
  parts.push(options.key.toUpperCase());
  return parts.join('+');
}
