import { describe, expect, it } from 'vitest'

import { DEFAULT_KEY_BINDINGS,
	 formatKeyBinding,
	 getConflictingShortcutActionIds,
	 isEditableEventTarget,
	 keyBindingFromKeyboardEvent,
	 resolveShortcutScope,
	 SHORTCUT_DEFINITIONS_BY_ID } from '@/lib/keyboardShortcuts'

describe ('keyboardShortcuts', () => {
  it ('defines the default key bindings used by the settings screen', () => {
    expect (SHORTCUT_DEFINITIONS_BY_ID['global.openShortcutHelp']).toMatchObject ({
	label: 'ショートカット一覧を開く',
	scope: 'global',
	defaultBinding: { key: '?', shift: true } })
    expect (DEFAULT_KEY_BINDINGS['global.focusSearch']).toEqual ({ key: '/' })
    expect (DEFAULT_KEY_BINDINGS['navigation.posts']).toEqual ({ key: 'p' })
    expect (DEFAULT_KEY_BINDINGS['pagination.next']).toEqual ({ key: 'ArrowRight' })
    expect (DEFAULT_KEY_BINDINGS['settings.theme']).toEqual ({ key: '3' })
  })

  it ('formats key bindings for display', () => {
    expect (formatKeyBinding ({ key: '?', shift: true })).toBe ('Shift + ?')
    expect (formatKeyBinding ({ key: '/' })).toBe ('/')
    expect (formatKeyBinding ({ key: 'p' })).toBe ('P')
    expect (formatKeyBinding ({ key: 'ArrowRight' })).toBe ('ArrowRight')
    expect (formatKeyBinding (null)).toBe ('未割当')
  })

  it ('normalises keyboard events without assigning space by default', () => {
    const event = { key: 'P',
		    ctrlKey: false,
		    shiftKey: false,
		    altKey: false,
		    metaKey: false } as KeyboardEvent

    expect (keyBindingFromKeyboardEvent (event)).toEqual ({ key: 'p' })
    expect (DEFAULT_KEY_BINDINGS['pagination.next']).not.toEqual ({ key: ' ' })
  })

  it ('detects conflicting action bindings', () => {
    const conflicts = getConflictingShortcutActionIds ({
	...DEFAULT_KEY_BINDINGS,
	'navigation.posts': { key: 'p' },
	'navigation.tags': { key: 'p' } })

    expect (conflicts.has ('navigation.posts')).toBe (true)
    expect (conflicts.has ('navigation.tags')).toBe (true)
    expect (conflicts.has ('navigation.wiki')).toBe (false)
  })

  it ('resolves route scopes and editable event targets', () => {
    const input = document.createElement ('input')
    const div = document.createElement ('div')
    div.setAttribute ('role', 'textbox')

    expect (resolveShortcutScope ('/posts/search')).toBe ('postSearch')
    expect (resolveShortcutScope ('/users/settings')).toBe ('settings')
    expect (resolveShortcutScope ('/materials/1')).toBe ('materials')
    expect (isEditableEventTarget (input)).toBe (true)
    expect (isEditableEventTarget (div)).toBe (true)
    expect (isEditableEventTarget (document.createElement ('button'))).toBe (false)
  })
})
