'use client';

/**
 * Global command registry for the command palette (Cmd+K).
 * Pages register their commands on mount, unregister on unmount.
 *
 * Usage:
 *   useCommands([
 *     {
 *       id: 'nav-issues',
 *       label: 'Go to Issues',
 *       group: 'Navigation',
 *       action: () => navigate('/project/x/issues'),
 *       shortcut: { key: 'i', meta: true },
 *       keywords: ['goto', 'navigate', 'issues'],
 *     },
 *   ]);
 */

import { useEffect, useCallback, useRef } from 'react';
import type { ReactNode } from 'react';

export interface ShortcutDisplay {
  key: string;
  meta?: boolean;
  ctrl?: boolean;
  shift?: boolean;
  alt?: boolean;
}

export interface CommandItem {
  id: string;
  /** Display label */
  label: string;
  /** Optional icon shown before the label */
  icon?: ReactNode;
  /** Optional keyboard shortcut hint */
  shortcut?: ShortcutDisplay;
  /** Group this command belongs to (used for section headers) */
  group: string;
  /** Called when the command is selected */
  action: () => void;
  /** Extra search keywords */
  keywords?: string[];
}

const registeredCommands: CommandItem[] = [];

/** Get all registered commands */
export function getRegisteredCommands(): CommandItem[] {
  return [...registeredCommands];
}

/**
 * Register a batch of commands. Returns a cleanup function.
 * Call inside useEffect (or component body since it auto-cleans on unmount).
 */
export function useCommands(commands: CommandItem[]): () => void {
  const commandsRef = useRef(commands);

  useEffect(() => {
    // Remove any existing commands with the same ids (handles StrictMode double-mount)
    const ids = new Set(commandsRef.current.map((c) => c.id));
    for (let i = registeredCommands.length - 1; i >= 0; i--) {
      if (ids.has(registeredCommands[i].id)) {
        registeredCommands.splice(i, 1);
      }
    }
    // Add new commands
    registeredCommands.push(...commandsRef.current);

    return () => {
      for (const c of commandsRef.current) {
        const idx = registeredCommands.findIndex((r) => r.id === c.id);
        if (idx !== -1) registeredCommands.splice(idx, 1);
      }
    };
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  return useCallback(() => {
    for (const c of commandsRef.current) {
      const idx = registeredCommands.findIndex((r) => r.id === c.id);
      if (idx !== -1) registeredCommands.splice(idx, 1);
    }
  }, []);
}
