/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */

import process from 'node:process';
import {
  type Command,
  type KeyBinding,
  type KeyBindingConfig,
  defaultKeyBindingConfig,
} from './keyBindings.js';

/**
 * Maps internal key names to user-friendly display names.
 */
const KEY_NAME_MAP: Record<string, string> = {
  enter: 'Enter',
  escape: 'Esc',
  backspace: 'Backspace',
  delete: 'Delete',
  up: 'Up',
  down: 'Down',
  left: 'Left',
  right: 'Right',
  pageup: 'Page Up',
  pagedown: 'Page Down',
  home: 'Home',
  end: 'End',
  tab: 'Tab',
  space: 'Space',
};

interface ModifierMap {
  ctrl: string;
  alt: string;
  shift: string;
  cmd: string;
}

const MODIFIER_MAPS: Record<string, ModifierMap> = {
  darwin: {
    ctrl: 'Ctrl',
    alt: 'Option',
    shift: 'Shift',
    cmd: 'Cmd',
  },
  win32: {
    ctrl: 'Ctrl',
    alt: 'Alt',
    shift: 'Shift',
    cmd: 'Win',
  },
  linux: {
    ctrl: 'Ctrl',
    alt: 'Alt',
    shift: 'Shift',
    cmd: 'Super',
  },
  default: {
    ctrl: 'Ctrl',
    alt: 'Alt',
    shift: 'Shift',
    cmd: 'Cmd/Win',
  },
};

/**
 * Formats a single KeyBinding into a human-readable string (e.g., "Ctrl+C").
 */
export function formatKeyBinding(
  binding: KeyBinding,
  platform?: string,
): string {
  const activePlatform =
    platform ??
    (process.env['FORCE_GENERIC_KEYBINDING_HINTS']
      ? 'default'
      : process.platform);
  const modMap = MODIFIER_MAPS[activePlatform] || MODIFIER_MAPS['default'];
  const parts: string[] = [];

  if (binding.ctrl) parts.push(modMap.ctrl);
  if (binding.alt) parts.push(modMap.alt);
  if (binding.shift) parts.push(modMap.shift);
  if (binding.cmd) parts.push(modMap.cmd);

  const keyName = KEY_NAME_MAP[binding.name] || binding.name.toUpperCase();
  parts.push(keyName);

  return parts.join('+');
}

/**
 * Formats the primary keybinding for a command.
 */
export function formatCommand(
  command: Command,
  config: KeyBindingConfig = defaultKeyBindingConfig,
  platform?: string,
): string {
  const bindings = config.get(command);
  if (!bindings || bindings.length === 0) {
    return '';
  }

  // Use the first binding as the primary one for display
  return formatKeyBinding(bindings[0], platform);
}
