import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import DropDownListSelect from '../src/canonical/DropDownListSelect.vue'
import CheckBox from '../src/canonical/CheckBox.vue'

const items = [
  { label: 'Alpha', value: 'a' },
  { label: 'Beta', value: 'b', disabled: true },
  { label: 'Gamma', value: 'c', checked: true },
]

describe('DropDownListSelect a11y (CANONICAL-016)', () => {
  it('exposes listbox + option roles and aria-selected from checked', () => {
    const wrapper = mount(DropDownListSelect, { props: { type: 'Radio', items } })
    const listbox = wrapper.find('[role="listbox"]')
    expect(listbox.exists()).toBe(true)
    expect(listbox.attributes('tabindex')).toBe('0')
    expect(listbox.attributes('aria-multiselectable')).toBe('false')
    const options = wrapper.findAll('[role="option"]')
    expect(options).toHaveLength(3)
    expect(options.every((o) => o.attributes('tabindex') === '-1')).toBe(true)
    expect(options[2].attributes('aria-selected')).toBe('true')
    expect(options[0].attributes('aria-selected')).toBe('false')
    expect(options[1].attributes('aria-disabled')).toBe('true')
  })

  it('sets aria-multiselectable true only for Multi type', () => {
    const wrapper = mount(DropDownListSelect, { props: { type: 'Multi', items } })
    expect(wrapper.find('[role="listbox"]').attributes('aria-multiselectable')).toBe('true')
  })

  it('ArrowDown moves active over enabled rows, skipping disabled, and tracks aria-activedescendant', async () => {
    const wrapper = mount(DropDownListSelect, { props: { type: 'Radio', items } })
    const listbox = wrapper.find('[role="listbox"]')
    await listbox.trigger('keydown', { key: 'ArrowDown' }) // -> index 0 (Alpha)
    expect(listbox.attributes('aria-activedescendant')).toBe('dropdown-opt-0')
    await listbox.trigger('keydown', { key: 'ArrowDown' }) // skips disabled index 1 -> index 2 (Gamma)
    expect(listbox.attributes('aria-activedescendant')).toBe('dropdown-opt-2')
  })

  it('ArrowUp wraps and Enter selects the active row', async () => {
    const wrapper = mount(DropDownListSelect, { props: { type: 'Radio', items } })
    const listbox = wrapper.find('[role="listbox"]')
    await listbox.trigger('keydown', { key: 'ArrowUp' }) // first enabled from bottom -> index 2 (Gamma)
    expect(listbox.attributes('aria-activedescendant')).toBe('dropdown-opt-2')
    await listbox.trigger('keydown', { key: 'Enter' })
    expect(wrapper.emitted('select')).toBeTruthy()
    expect(wrapper.emitted('select')![0]).toEqual(['c'])
  })

  it('Space selects active row and Escape emits close', async () => {
    const wrapper = mount(DropDownListSelect, { props: { type: 'Radio', items } })
    const listbox = wrapper.find('[role="listbox"]')
    await listbox.trigger('keydown', { key: 'ArrowDown' }) // index 0 (Alpha)
    await listbox.trigger('keydown', { key: ' ' })
    expect(wrapper.emitted('select')![0]).toEqual(['a'])
    await listbox.trigger('keydown', { key: 'Escape' })
    expect(wrapper.emitted('close')).toBeTruthy()
  })

  it('never selects a disabled row via keyboard', async () => {
    const wrapper = mount(DropDownListSelect, { props: { type: 'Radio', items } })
    const listbox = wrapper.find('[role="listbox"]')
    // Home -> first enabled (index 0). Manually verify disabled is unreachable as active.
    await listbox.trigger('keydown', { key: 'Home' })
    expect(listbox.attributes('aria-activedescendant')).toBe('dropdown-opt-0')
    await listbox.trigger('keydown', { key: 'End' })
    expect(listbox.attributes('aria-activedescendant')).toBe('dropdown-opt-2')
  })
})

describe('DropDownListSelect Multi check uses canonical CheckBox (CANONICAL-012)', () => {
  it('renders a display-only CheckBox per row reflecting checked + disabled, not an inline span', () => {
    const wrapper = mount(DropDownListSelect, { props: { type: 'Multi', items } })
    // no hand-rolled affordance left
    expect(wrapper.find('.dropdown-item__check-icon').exists()).toBe(false)
    const boxes = wrapper.findAllComponents(CheckBox)
    expect(boxes).toHaveLength(3)
    // all readonly (display-only) so the row owns interaction
    expect(boxes.every((b) => b.props('readonly') === true)).toBe(true)
    // status mirrors item.checked; enable mirrors item.disabled
    expect(boxes[2].props('status')).toBe('on') // Gamma checked
    expect(boxes[0].props('status')).toBe('off') // Alpha unchecked
    expect(boxes[1].props('enable')).toBe('no') // Beta disabled
    expect(boxes[0].props('enable')).toBe('yes')
  })

  it('non-Multi types render no CheckBox', () => {
    const wrapper = mount(DropDownListSelect, { props: { type: 'Radio', items } })
    expect(wrapper.findAllComponents(CheckBox)).toHaveLength(0)
  })

  it('clicking a Multi row still emits select (CheckBox does not swallow the click)', async () => {
    const wrapper = mount(DropDownListSelect, { props: { type: 'Multi', items } })
    await wrapper.findAll('[role="option"]')[0].trigger('click')
    expect(wrapper.emitted('select')).toBeTruthy()
    expect(wrapper.emitted('select')![0]).toEqual(['a'])
  })
})
