import { useEffect, useRef } from 'react';
import type { EditorStore } from '../store/editorStore';

// ── Platform detection ────────────────────────────────────────────────────────
// Computed once at module load — safe because the user's platform never changes.

const _isMac = typeof navigator !== 'undefined' && /Mac|iPhone|iPad|iPod/.test(navigator.platform);
const _m     = _isMac ? '⌘'      : 'Ctrl+';
const _s     = _isMac ? '⇧'      : 'Shift+';

// ── Shortcut label registry ───────────────────────────────────────────────────
// Import this object anywhere that needs to display a shortcut string
// (context menus, tooltips, help panels, etc.).

export const SHORTCUT_LABELS: Record<string, string> = {
  undo:       `${_m}Z`,
  redo:       `${_m}Y`,
  redoAlt:    `${_m}${_s}Z`,
  save:       `${_m}S`,
  openCmd:    `${_m}K`,
  openFinder: `${_m}P`,
  copy:       `${_m}C`,
  paste:      `${_m}V`,
  duplicate:  `${_m}D`,
  copyStyle:  `${_m}${_s}C`,
  pasteStyle: `${_m}${_s}V`,
  delete:     'Del',
  escape:     'Esc',
};

// ── Guard ─────────────────────────────────────────────────────────────────────
// Returns true when focus is inside a field that owns the keyboard.

function inEditable(e: KeyboardEvent): boolean {
  const el = e.target as HTMLElement | null;
  if (!el) return false;
  const tag = el.tagName;
  if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return true;
  if (el.isContentEditable) return true;
  return false;
}

// ── Hook ─────────────────────────────────────────────────────────────────────
// Mount once at the root (App.tsx). Uses a ref so the handler never goes stale
// and the effect never needs to re-register.

export function useShortcuts(store: EditorStore): void {
  // Stable ref — always points at the latest store without re-subscribing
  const ref = useRef(store);
  ref.current = store;

  useEffect(() => {
    const handler = (e: KeyboardEvent) => {
      const isMac = /Mac|iPhone|iPad|iPod/.test(navigator.platform);
      const mod   = isMac ? e.metaKey : e.ctrlKey;
      const key   = e.key.toLowerCase();

      // ── Ctrl+K: open command palette ─────────────────────────────────────
      if (mod && key === 'k') {
        e.preventDefault();
        window.dispatchEvent(new CustomEvent('cb:openCmd'));
        return;
      }

      // ── Ctrl+P: open global finder ────────────────────────────────────────
      if (mod && key === 'p') {
        e.preventDefault();
        window.dispatchEvent(new CustomEvent('cb:openFinder'));
        return;
      }

      // ── All other shortcuts: skip when typing ─────────────────────────────
      if (inEditable(e)) return;

      const s = ref.current;

      // ── Undo ─────────────────────────────────────────────────────────────
      if (mod && key === 'z' && !e.shiftKey) {
        e.preventDefault(); s.undo(); return;
      }

      // ── Redo (Ctrl+Y  or  Ctrl+Shift+Z) ──────────────────────────────────
      if (mod && (key === 'y' || (key === 'z' && e.shiftKey))) {
        e.preventDefault(); s.redo(); return;
      }

      // ── Save ─────────────────────────────────────────────────────────────
      if (mod && key === 's') {
        e.preventDefault();
        window.dispatchEvent(new CustomEvent('cb:save'));
        return;
      }

      // ── Node operations ───────────────────────────────────────────────────
      const sel = s.state.selectedId;

      if (mod && key === 'c') {
        e.preventDefault();
        if (sel) s.copyNode(sel);
        return;
      }
      if (mod && key === 'v') {
        e.preventDefault();
        if (sel) s.pasteNode(sel);
        return;
      }
      if (mod && key === 'd') {
        e.preventDefault();
        if (sel) s.duplicateNode(sel);
        return;
      }

      // ── Delete / Backspace ────────────────────────────────────────────────
      if ((e.key === 'Delete' || e.key === 'Backspace') && sel) {
        e.preventDefault();
        s.deleteNode(sel);
        return;
      }

      // ── Escape: deselect node (Canvas closes its own menus separately) ────
      if (e.key === 'Escape') {
        s.selectNode(null);
      }
    };

    window.addEventListener('keydown', handler);
    return () => window.removeEventListener('keydown', handler);
  }, []); // empty dep — stable via ref
}
