import { useCallback, useRef } from 'react'
import type { AiAgentId, AiAgentsStatus } from '../lib/aiAgents'
import type { AppLocale, UiLanguagePreference } from '../lib/i18n'
import type { ThemeMode } from '../lib/themeMode'
import type { VaultAiGuidanceStatus } from '../lib/vaultAiGuidance'
import { useAppKeyboard } from './useAppKeyboard'
import { useCommandRegistry } from './useCommandRegistry'
import type { CommandAction } from './useCommandRegistry'
import { useKeyboardNavigation } from './useKeyboardNavigation'
import { useMenuEvents } from './useMenuEvents'
import type { NoteWidthMode, SidebarSelection, SidebarFilter, VaultEntry } from '../types'
import { requestAddRemote } from '../utils/addRemoteEvents'
import type { NoteListFilter } from '../utils/noteListHelpers'
import type { ViewMode } from './useViewMode'
import type { ImmediateCreateOptions } from './useNoteCreation'
import type { NoteListMultiSelectionCommands } from '../components/note-list/multiSelectionCommands'
import type { GitRepositoryOption } from '../utils/gitRepositories'
import type { RichEditorBlockTypeDefinition } from '../utils/richEditorBlockTypes'

interface AppCommandsConfig {
  activeTabPath: string | null
  activeTabPathRef: React.MutableRefObject<string | null>
  entries: VaultEntry[]
  visibleNotesRef: React.RefObject<VaultEntry[]>
  multiSelectionCommandRef: React.MutableRefObject<NoteListMultiSelectionCommands | null>
  modifiedCount: number
  selection: SidebarSelection
  onQuickOpen: () => void
  onCommandPalette: () => void
  onSearch: () => void
  onFindInNote?: () => void
  onUndo?: () => void
  onRedo?: () => void
  canUndo?: boolean
  canRedo?: boolean
  undoLabel?: string | null
  redoLabel?: string | null
  onReplaceInNote?: () => void
  onPastePlainText: () => void
  onCreateNote: (type?: string, options?: ImmediateCreateOptions) => void
  onCreateNoteOfType: (type: string) => void
  onSave: () => void
  onOpenSettings: () => void
  onOpenFeedback?: () => void
  onDeleteNote: (path: string) => void
  onArchiveNote: (path: string) => void
  onUnarchiveNote: (path: string) => void
  onCommitPush: () => void
  onGenerateCommitMessage?: () => void
  onPull?: () => void
  onPullRepository?: (path: string) => void
  onResolveConflicts?: () => void
  onSetViewMode: (mode: ViewMode) => void
  onToggleInspector: () => void
  onToggleDiff?: () => void
  onToggleRawEditor?: () => void
  selectedViewName?: string
  onMoveSelectedViewUp?: () => void
  onMoveSelectedViewDown?: () => void
  canMoveSelectedViewUp?: boolean
  canMoveSelectedViewDown?: boolean
  noteWidth?: NoteWidthMode
  defaultNoteWidth?: NoteWidthMode
  onSetNoteWidth?: (mode: NoteWidthMode) => void
  onSetDefaultNoteWidth?: (mode: NoteWidthMode) => void
  activeNoteModified: boolean
  onZoomIn: () => void
  onZoomOut: () => void
  onZoomReset: () => void
  zoomLevel: number
  onSelect: (sel: SidebarSelection) => void
  onRenameFolder?: () => void
  onDeleteFolder?: () => void
  showInbox?: boolean
  onReplaceActiveTab: (entry: VaultEntry) => void
  onSelectNote: (entry: VaultEntry) => void
  onGoBack?: () => void
  onGoForward?: () => void
  canGoBack?: boolean
  canGoForward?: boolean
  onOpenVault?: () => void
  onCreateEmptyVault?: () => void
  onAddRemote?: () => void
  canAddRemote?: boolean
  gitFeaturesEnabled?: boolean
  isGitVault?: boolean
  gitRepositories?: GitRepositoryOption[]
  onInitializeGit?: () => void
  onCreateType?: () => void
  aiFeaturesEnabled?: boolean
  onToggleAIChat?: () => void
  onToggleTableOfContents?: () => void
  onCheckForUpdates?: () => void
  onRemoveActiveVault?: () => void
  onRestoreGettingStarted?: () => void
  isGettingStartedHidden?: boolean
  vaultCount?: number
  locale?: AppLocale
  systemLocale?: AppLocale
  selectedUiLanguage?: UiLanguagePreference
  onSetUiLanguage?: (language: UiLanguagePreference) => void
  onSetThemeMode?: (mode: ThemeMode) => void
  mcpStatus?: string
  onInstallMcp?: () => void
  aiAgentsStatus?: AiAgentsStatus
  vaultAiGuidanceStatus?: VaultAiGuidanceStatus
  onOpenAiAgents?: () => void
  onRestoreVaultAiGuidance?: () => void
  onSetDefaultAiAgent?: (agent: AiAgentId) => void
  selectedAiAgent?: AiAgentId
  onCycleDefaultAiAgent?: () => void
  selectedAiAgentLabel?: string
  claudeCodeStatus?: string
  claudeCodeVersion?: string
  onReloadVault?: () => void
  onRepairVault?: () => void
  onSetNoteIcon?: () => void
  onRemoveNoteIcon?: () => void
  onChangeNoteType?: () => void
  onMoveNoteToFolder?: () => void
  canMoveNoteToFolder?: boolean
  onTurnCurrentBlockInto?: (target: RichEditorBlockTypeDefinition) => void
  activeNoteHasIcon?: boolean
  noteListFilter?: NoteListFilter
  onSetNoteListFilter?: (filter: NoteListFilter) => void
  onOpenInNewWindow?: () => void
  onRevealActiveFile?: (path: string) => void
  onCopyActiveFilePath?: (path: string) => void
  onCopyActiveDeepLink?: (path: string) => void
  onOpenActiveFileExternal?: (path: string) => void
  onExportNoteAsPdf?: () => void
  onRevealSelectedFolder?: () => void
  onCopySelectedFolderPath?: () => void
  onToggleFavorite?: (path: string) => void
  onToggleOrganized?: (path: string) => void
  onCustomizeNoteListColumns?: () => void
  canCustomizeNoteListColumns?: boolean
  noteListColumnsLabel?: string
  onRestoreDeletedNote?: () => void
  canRestoreDeletedNote?: boolean
}

type CommandRegistryConfig = Parameters<typeof useCommandRegistry>[0]
type CommandRegistrySelectionState = Pick<
  CommandRegistryConfig,
  | 'activeNoteModified'
  | 'onZoomIn'
  | 'onZoomOut'
  | 'onZoomReset'
  | 'zoomLevel'
  | 'onSelect'
  | 'onRenameFolder'
  | 'onDeleteFolder'
  | 'onRevealSelectedFolder'
  | 'onCopySelectedFolderPath'
  | 'showInbox'
  | 'onGoBack'
  | 'onGoForward'
  | 'canGoBack'
  | 'canGoForward'
  | 'selection'
>
type CommandRegistryCoreActions = Pick<
  CommandRegistryConfig,
  | 'activeTabPath'
  | 'entries'
  | 'modifiedCount'
  | 'onQuickOpen'
  | 'onCreateNote'
  | 'onCreateNoteOfType'
  | 'onSave'
  | 'onUndo'
  | 'onRedo'
  | 'canUndo'
  | 'canRedo'
  | 'undoLabel'
  | 'redoLabel'
  | 'onFindInNote'
  | 'onReplaceInNote'
  | 'onPastePlainText'
  | 'onTurnCurrentBlockInto'
  | 'onOpenSettings'
  | 'onOpenFeedback'
  | 'onDeleteNote'
  | 'onArchiveNote'
  | 'onUnarchiveNote'
  | 'onCommitPush'
  | 'onGenerateCommitMessage'
  | 'onPull'
  | 'onPullRepository'
  | 'onResolveConflicts'
  | 'onSetViewMode'
  | 'onToggleInspector'
  | 'onToggleDiff'
  | 'onToggleRawEditor'
  | 'selectedViewName'
  | 'onMoveSelectedViewUp'
  | 'onMoveSelectedViewDown'
  | 'canMoveSelectedViewUp'
  | 'canMoveSelectedViewDown'
  | 'noteWidth'
  | 'defaultNoteWidth'
  | 'onSetNoteWidth'
  | 'onSetDefaultNoteWidth'
  | 'onToggleAIChat'
  | 'onToggleTableOfContents'
>
type CommandRegistryVaultActions = Pick<
  CommandRegistryConfig,
  | 'onOpenVault'
  | 'onCreateEmptyVault'
  | 'onAddRemote'
  | 'canAddRemote'
  | 'gitFeaturesEnabled'
  | 'isGitVault'
  | 'gitRepositories'
  | 'onInitializeGit'
  | 'onCheckForUpdates'
  | 'onCreateType'
  | 'locale'
  | 'systemLocale'
  | 'selectedUiLanguage'
  | 'onSetUiLanguage'
  | 'onSetThemeMode'
  | 'onRemoveActiveVault'
  | 'onRestoreGettingStarted'
  | 'isGettingStartedHidden'
  | 'vaultCount'
  | 'onReloadVault'
  | 'onRepairVault'
  | 'onOpenInNewWindow'
  | 'onRevealActiveFile'
  | 'onCopyActiveFilePath'
  | 'onCopyActiveDeepLink'
  | 'onOpenActiveFileExternal'
  | 'onRestoreDeletedNote'
  | 'canRestoreDeletedNote'
>
type CommandRegistryAiActions = Pick<
  CommandRegistryConfig,
  | 'aiFeaturesEnabled'
  | 'mcpStatus'
  | 'onInstallMcp'
  | 'aiAgentsStatus'
  | 'vaultAiGuidanceStatus'
  | 'onOpenAiAgents'
  | 'onRestoreVaultAiGuidance'
  | 'onSetDefaultAiAgent'
  | 'selectedAiAgent'
  | 'onCycleDefaultAiAgent'
  | 'selectedAiAgentLabel'
>
type CommandRegistryNoteActions = Pick<
  CommandRegistryConfig,
  | 'onSetNoteIcon'
  | 'onRemoveNoteIcon'
  | 'onChangeNoteType'
  | 'onMoveNoteToFolder'
  | 'canMoveNoteToFolder'
  | 'onTurnCurrentBlockInto'
  | 'activeNoteHasIcon'
  | 'noteListFilter'
  | 'onSetNoteListFilter'
  | 'onToggleFavorite'
  | 'onToggleOrganized'
  | 'onCustomizeNoteListColumns'
  | 'canCustomizeNoteListColumns'
  | 'noteListColumnsLabel'
  | 'onExportNoteAsPdf'
>

function aiFeaturesAreEnabled(config: Pick<AppCommandsConfig, 'aiFeaturesEnabled'>): boolean {
  return config.aiFeaturesEnabled !== false
}

function enabledAiChatToggle(config: Pick<AppCommandsConfig, 'aiFeaturesEnabled' | 'onToggleAIChat'>): (() => void) | undefined {
  return aiFeaturesAreEnabled(config) ? config.onToggleAIChat : undefined
}

function createKeyboardActions(
  config: AppCommandsConfig,
): Omit<Parameters<typeof useAppKeyboard>[0], 'onArchiveNote'> {
  return {
    onQuickOpen: config.onQuickOpen,
    onCommandPalette: config.onCommandPalette,
    onSearch: config.onSearch,
    onFindInNote: config.onFindInNote,
    onReplaceInNote: config.onReplaceInNote,
    onPastePlainText: config.onPastePlainText,
    onCreateNote: config.onCreateNote,
    onSave: config.onSave,
    onUndo: config.onUndo,
    onRedo: config.onRedo,
    canUndo: config.canUndo,
    canRedo: config.canRedo,
    onOpenSettings: config.onOpenSettings,
    onDeleteNote: config.onDeleteNote,
    onSetViewMode: config.onSetViewMode,
    onZoomIn: config.onZoomIn,
    onZoomOut: config.onZoomOut,
    onZoomReset: config.onZoomReset,
    onGoBack: config.onGoBack,
    onGoForward: config.onGoForward,
    onToggleAIChat: enabledAiChatToggle(config),
    onToggleTableOfContents: config.onToggleTableOfContents,
    onToggleRawEditor: config.onToggleRawEditor,
    onToggleInspector: config.onToggleInspector,
    onToggleFavorite: config.onToggleFavorite,
    onToggleOrganized: config.onToggleOrganized,
    onOpenInNewWindow: config.onOpenInNewWindow,
    activeTabPathRef: config.activeTabPathRef,
    multiSelectionCommandRef: config.multiSelectionCommandRef,
  }
}

function createMenuEventHandlers(
  config: AppCommandsConfig,
  selectFilter: (filter: SidebarFilter) => void,
  viewChanges: () => void,
): Omit<Parameters<typeof useMenuEvents>[0], 'onArchiveNote'> {
  return {
    ...createMenuEventActionHandlers(config, selectFilter),
    ...createMenuEventVaultHandlers(config, viewChanges),
    ...createMenuEventState(config),
  }
}

function createMenuEventActionHandlers(
  config: AppCommandsConfig,
  selectFilter: (filter: SidebarFilter) => void,
): Pick<
  Omit<Parameters<typeof useMenuEvents>[0], 'onArchiveNote'>,
  | 'onSetViewMode'
  | 'onCreateNote'
  | 'onCreateType'
  | 'onQuickOpen'
  | 'onSave'
  | 'onOpenSettings'
  | 'onToggleInspector'
  | 'onCommandPalette'
  | 'onZoomIn'
  | 'onZoomOut'
  | 'onZoomReset'
  | 'onDeleteNote'
  | 'onFindInNote'
  | 'onUndo'
  | 'onRedo'
  | 'onReplaceInNote'
  | 'onPastePlainText'
  | 'onSearch'
  | 'onToggleRawEditor'
  | 'onToggleDiff'
  | 'onToggleAIChat'
  | 'onToggleTableOfContents'
  | 'onExportNoteAsPdf'
  | 'onToggleOrganized'
  | 'onGoBack'
  | 'onGoForward'
  | 'onCheckForUpdates'
  | 'onSelectFilter'
> {
  return {
    onSetViewMode: config.onSetViewMode,
    onCreateNote: config.onCreateNote,
    onCreateType: config.onCreateType,
    onQuickOpen: config.onQuickOpen,
    onSave: config.onSave,
    onOpenSettings: config.onOpenSettings,
    onToggleInspector: config.onToggleInspector,
    onCommandPalette: config.onCommandPalette,
    onZoomIn: config.onZoomIn,
    onZoomOut: config.onZoomOut,
    onZoomReset: config.onZoomReset,
    onDeleteNote: config.onDeleteNote,
    onFindInNote: config.onFindInNote,
    onUndo: config.onUndo,
    onRedo: config.onRedo,
    onReplaceInNote: config.onReplaceInNote,
    onPastePlainText: config.onPastePlainText,
    onSearch: config.onSearch,
    onToggleRawEditor: config.onToggleRawEditor,
    onToggleDiff: config.onToggleDiff,
    onToggleAIChat: enabledAiChatToggle(config),
    onToggleTableOfContents: config.onToggleTableOfContents,
    onExportNoteAsPdf: config.onExportNoteAsPdf,
    onToggleOrganized: config.onToggleOrganized,
    onGoBack: config.onGoBack,
    onGoForward: config.onGoForward,
    onCheckForUpdates: config.onCheckForUpdates,
    onSelectFilter: selectFilter,
  }
}

function createMenuEventVaultHandlers(
  config: AppCommandsConfig,
  viewChanges: () => void,
): Pick<
  Omit<Parameters<typeof useMenuEvents>[0], 'onArchiveNote'>,
  | 'onOpenVault'
  | 'onRemoveActiveVault'
  | 'onRestoreGettingStarted'
  | 'onAddRemote'
  | 'onCommitPush'
  | 'onPull'
  | 'onResolveConflicts'
  | 'onViewChanges'
  | 'onInstallMcp'
  | 'onReloadVault'
  | 'onRepairVault'
  | 'onOpenInNewWindow'
  | 'onRestoreDeletedNote'
> {
  return {
    onOpenVault: config.onOpenVault,
    onRemoveActiveVault: config.onRemoveActiveVault,
    onRestoreGettingStarted: config.onRestoreGettingStarted,
    onAddRemote: config.onAddRemote ?? requestAddRemote,
    onCommitPush: config.onCommitPush,
    onPull: config.onPull,
    onResolveConflicts: config.onResolveConflicts,
    onViewChanges: viewChanges,
    onInstallMcp: config.onInstallMcp,
    onReloadVault: config.onReloadVault,
    onRepairVault: config.onRepairVault,
    onOpenInNewWindow: config.onOpenInNewWindow,
    onRestoreDeletedNote: config.onRestoreDeletedNote,
  }
}

function createMenuEventState(
  config: AppCommandsConfig,
): Pick<
  Omit<Parameters<typeof useMenuEvents>[0], 'onArchiveNote'>,
  | 'activeTabPathRef'
  | 'multiSelectionCommandRef'
  | 'activeTabPath'
  | 'modifiedCount'
  | 'hasRestorableDeletedNote'
  | 'hasNoRemote'
> {
  return {
    activeTabPathRef: config.activeTabPathRef,
    multiSelectionCommandRef: config.multiSelectionCommandRef,
    activeTabPath: config.activeTabPath,
    modifiedCount: config.modifiedCount,
    hasRestorableDeletedNote: config.canRestoreDeletedNote,
    hasNoRemote: config.canAddRemote ?? true,
  }
}

function createCommandRegistrySelectionConfig(
  config: AppCommandsConfig,
): CommandRegistrySelectionState {
  return {
    activeNoteModified: config.activeNoteModified,
    onZoomIn: config.onZoomIn,
    onZoomOut: config.onZoomOut,
    onZoomReset: config.onZoomReset,
    zoomLevel: config.zoomLevel,
    onSelect: config.onSelect,
    onRenameFolder: config.onRenameFolder,
    onDeleteFolder: config.onDeleteFolder,
    onRevealSelectedFolder: config.onRevealSelectedFolder,
    onCopySelectedFolderPath: config.onCopySelectedFolderPath,
    showInbox: config.showInbox,
    onGoBack: config.onGoBack,
    onGoForward: config.onGoForward,
    canGoBack: config.canGoBack,
    canGoForward: config.canGoForward,
    selection: config.selection,
  }
}

function createCommandRegistryCoreConfig(
  config: AppCommandsConfig,
): CommandRegistryCoreActions {
  return {
    activeTabPath: config.activeTabPath,
    entries: config.entries,
    modifiedCount: config.modifiedCount,
    onQuickOpen: config.onQuickOpen,
    onCreateNote: config.onCreateNote,
    onCreateNoteOfType: config.onCreateNoteOfType,
    onSave: config.onSave,
    onUndo: config.onUndo,
    onRedo: config.onRedo,
    canUndo: config.canUndo,
    canRedo: config.canRedo,
    undoLabel: config.undoLabel,
    redoLabel: config.redoLabel,
    onOpenSettings: config.onOpenSettings,
    onOpenFeedback: config.onOpenFeedback,
    onDeleteNote: config.onDeleteNote,
    onArchiveNote: config.onArchiveNote,
    onUnarchiveNote: config.onUnarchiveNote,
    onCommitPush: config.onCommitPush,
    onGenerateCommitMessage: config.onGenerateCommitMessage,
    onPull: config.onPull,
    onPullRepository: config.onPullRepository,
    onResolveConflicts: config.onResolveConflicts,
    onSetViewMode: config.onSetViewMode,
    onToggleInspector: config.onToggleInspector,
    onToggleDiff: config.onToggleDiff,
    onToggleRawEditor: config.onToggleRawEditor,
    selectedViewName: config.selectedViewName,
    onMoveSelectedViewUp: config.onMoveSelectedViewUp,
    onMoveSelectedViewDown: config.onMoveSelectedViewDown,
    canMoveSelectedViewUp: config.canMoveSelectedViewUp,
    canMoveSelectedViewDown: config.canMoveSelectedViewDown,
    onFindInNote: config.onFindInNote,
    onReplaceInNote: config.onReplaceInNote,
    onPastePlainText: config.onPastePlainText,
    onTurnCurrentBlockInto: config.onTurnCurrentBlockInto,
    noteWidth: config.noteWidth,
    defaultNoteWidth: config.defaultNoteWidth,
    onSetNoteWidth: config.onSetNoteWidth,
    onSetDefaultNoteWidth: config.onSetDefaultNoteWidth,
    onToggleAIChat: enabledAiChatToggle(config),
    onToggleTableOfContents: config.onToggleTableOfContents,
  }
}

function createCommandRegistryVaultConfig(
  config: AppCommandsConfig,
): CommandRegistryVaultActions {
  return {
    onOpenVault: config.onOpenVault,
    onCreateEmptyVault: config.onCreateEmptyVault,
    onAddRemote: config.onAddRemote ?? requestAddRemote,
    canAddRemote: config.canAddRemote ?? true,
    gitFeaturesEnabled: config.gitFeaturesEnabled,
    isGitVault: config.isGitVault,
    gitRepositories: config.gitRepositories,
    onInitializeGit: config.onInitializeGit,
    onCheckForUpdates: config.onCheckForUpdates,
    onCreateType: config.onCreateType,
    locale: config.locale,
    systemLocale: config.systemLocale,
    selectedUiLanguage: config.selectedUiLanguage,
    onSetUiLanguage: config.onSetUiLanguage,
    onSetThemeMode: config.onSetThemeMode,
    onRemoveActiveVault: config.onRemoveActiveVault,
    onRestoreGettingStarted: config.onRestoreGettingStarted,
    isGettingStartedHidden: config.isGettingStartedHidden,
    vaultCount: config.vaultCount,
    onReloadVault: config.onReloadVault,
    onRepairVault: config.onRepairVault,
    onOpenInNewWindow: config.onOpenInNewWindow,
    onRevealActiveFile: config.onRevealActiveFile,
    onCopyActiveFilePath: config.onCopyActiveFilePath,
    onCopyActiveDeepLink: config.onCopyActiveDeepLink,
    onOpenActiveFileExternal: config.onOpenActiveFileExternal,
    onRestoreDeletedNote: config.onRestoreDeletedNote,
    canRestoreDeletedNote: config.canRestoreDeletedNote,
  }
}

function createCommandRegistryAiConfig(
  config: AppCommandsConfig,
): CommandRegistryAiActions {
  const aiFeaturesEnabled = aiFeaturesAreEnabled(config)
  const sharedConfig = {
    aiFeaturesEnabled,
    mcpStatus: config.mcpStatus,
    onInstallMcp: config.onInstallMcp,
  }

  if (!aiFeaturesEnabled) return sharedConfig

  return {
    ...sharedConfig,
    aiAgentsStatus: config.aiAgentsStatus,
    vaultAiGuidanceStatus: config.vaultAiGuidanceStatus,
    onOpenAiAgents: config.onOpenAiAgents,
    onRestoreVaultAiGuidance: config.onRestoreVaultAiGuidance,
    onSetDefaultAiAgent: config.onSetDefaultAiAgent,
    selectedAiAgent: config.selectedAiAgent,
    onCycleDefaultAiAgent: config.onCycleDefaultAiAgent,
    selectedAiAgentLabel: config.selectedAiAgentLabel,
  }
}

function createCommandRegistryNoteConfig(
  config: AppCommandsConfig,
): CommandRegistryNoteActions {
  return {
    onSetNoteIcon: config.onSetNoteIcon,
    onRemoveNoteIcon: config.onRemoveNoteIcon,
    onChangeNoteType: config.onChangeNoteType,
    onMoveNoteToFolder: config.onMoveNoteToFolder,
    canMoveNoteToFolder: config.canMoveNoteToFolder,
    activeNoteHasIcon: config.activeNoteHasIcon,
    noteListFilter: config.noteListFilter,
    onSetNoteListFilter: config.onSetNoteListFilter,
    onToggleFavorite: config.onToggleFavorite,
    onToggleOrganized: config.onToggleOrganized,
    onCustomizeNoteListColumns: config.onCustomizeNoteListColumns,
    canCustomizeNoteListColumns: config.canCustomizeNoteListColumns,
    noteListColumnsLabel: config.noteListColumnsLabel,
    onExportNoteAsPdf: config.onExportNoteAsPdf,
  }
}

function createCommandRegistryConfig(config: AppCommandsConfig): CommandRegistryConfig {
  return {
    ...createCommandRegistryCoreConfig(config),
    ...createCommandRegistrySelectionConfig(config),
    ...createCommandRegistryVaultConfig(config),
    ...createCommandRegistryAiConfig(config),
    ...createCommandRegistryNoteConfig(config),
  }
}

/** Sets up keyboard shortcuts, command registry, menu events, and keyboard navigation. */
export function useAppCommands(config: AppCommandsConfig): CommandAction[] {
  const entriesRef = useRef(config.entries)
  // eslint-disable-next-line react-hooks/refs
  entriesRef.current = config.entries

  const toggleArchive = useCallback((path: string) => {
    const entry = entriesRef.current.find(e => e.path === path)
    ;(entry?.archived ? config.onUnarchiveNote : config.onArchiveNote)(path)
  }, [config.onArchiveNote, config.onUnarchiveNote])


  const { onSelect } = config

  const selectFilter = useCallback((filter: SidebarFilter) => {
    const safeFilter = !config.showInbox && filter === 'inbox' ? 'all' : filter
    onSelect({ kind: 'filter', filter: safeFilter })
  }, [config.showInbox, onSelect])

  const viewChanges = useCallback(() => {
    onSelect({ kind: 'filter', filter: 'changes' })
  }, [onSelect])

  const keyboardActions = createKeyboardActions(config)
  const menuEventHandlers = createMenuEventHandlers(config, selectFilter, viewChanges)

  useAppKeyboard({ ...keyboardActions, onArchiveNote: toggleArchive })

  useMenuEvents({ ...menuEventHandlers, onArchiveNote: toggleArchive })

  const commands = useCommandRegistry(createCommandRegistryConfig(config))

  useKeyboardNavigation({
    activeTabPath: config.activeTabPath,
    visibleNotesRef: config.visibleNotesRef,
    onReplaceActiveTab: config.onReplaceActiveTab,
    onSelectNote: config.onSelectNote,
  })

  return commands
}
