'use client';

import {useEffect} from 'react';
import {useLoyalyAi} from '@/features/loyaly-ai/providers/LoyalyAiProvider';
import {useAccountMenu} from './AccountMenuProvider';
import {useSidebar} from './SidebarProvider';
import {WORKSPACE_SHORTCUTS, type ShortcutId} from './shortcuts';

/** Where a keystroke belongs to the field, not the app. */
function isTyping(target: EventTarget | null): boolean {
  if (!(target instanceof HTMLElement)) return false;
  return (
    target.isContentEditable ||
    ['INPUT', 'TEXTAREA', 'SELECT'].includes(target.tagName)
  );
}

/**
 * Binds the shortcuts listed in shortcuts.ts. Mounted once, by the shell.
 *
 * Every one of them drives a control that already exists — the sidebar toggle,
 * the Loyaly AI toggle, the shortcuts dialog — so nothing here is reachable only
 * by keyboard. That is the rule the Kbd guidance states: a shortcut supplements
 * a visible control, it does not replace one.
 */
export function useWorkspaceShortcuts() {
  const {toggle: toggleSidebar} = useSidebar();
  const {toggle: toggleLoyalyAi} = useLoyalyAi();
  const {openDialog} = useAccountMenu();

  useEffect(() => {
    const actions: Record<ShortcutId, () => void> = {
      toggleSidebar,
      toggleLoyalyAi,
      showShortcuts: () => openDialog('shortcuts'),
    };

    const onKeyDown = (event: KeyboardEvent) => {
      // metaKey on macOS, ctrlKey elsewhere — the same either/or `mod` renders
      // as. Not `event.getModifierState`, which cannot express that choice.
      if (!(event.metaKey || event.ctrlKey) || event.altKey) return;
      if (isTyping(event.target)) return;

      const key = event.key.toLowerCase();
      const match = WORKSPACE_SHORTCUTS.find(
        (shortcut) => shortcut.binding === key && shortcut.id,
      );
      if (!match?.id) return;

      event.preventDefault();
      actions[match.id]();
    };

    window.addEventListener('keydown', onKeyDown);
    return () => window.removeEventListener('keydown', onKeyDown);
  }, [toggleSidebar, toggleLoyalyAi, openDialog]);
}
