import { fixture, assert, html } from '@open-wc/testing'
import { sendKeys } from '@web/test-runner-commands'
import CurrencyPicker from '../../../src/elements/currency/internals/Picker.js'
import '../../../src/elements/currency/currency-picker.js'

describe('CurrencyPicker - Accessibility', () => {
  async function basicFixture(): Promise<CurrencyPicker> {
    return fixture(html`<currency-picker label="Select Currency"></currency-picker>`)
  }

  async function multiSelectFixture(): Promise<CurrencyPicker> {
    return fixture(html`<currency-picker multi label="Select Multiple Currencies"></currency-picker>`)
  }

  async function errorStateFixture(): Promise<CurrencyPicker> {
    return fixture(html`<currency-picker required label="Required Currency Selection"></currency-picker>`)
  }

  describe('ARIA Attributes', () => {
    let picker: CurrencyPicker

    beforeEach(async () => {
      picker = await basicFixture()
    })

    it('should have proper ARIA roles', async () => {
      const container = picker.shadowRoot?.querySelector('.currency-picker')
      assert.equal(container?.getAttribute('role'), 'group')
    })

    it('should have descriptive ARIA labels', async () => {
      const container = picker.shadowRoot?.querySelector('.currency-picker')
      const ariaLabel = container?.getAttribute('aria-label')

      assert.exists(ariaLabel)
      assert.include(ariaLabel || '', 'Currency selector')
    })

    it('should update ARIA labels when selection changes', async () => {
      picker.selected = ['USD']
      await picker.updateComplete

      const container = picker.shadowRoot?.querySelector('.currency-picker')
      const ariaLabel = container?.getAttribute('aria-label')

      assert.include(ariaLabel || '', 'USD selected')
    })

    it('should have proper ARIA invalid state', async () => {
      picker.required = true
      picker.clearSelection()
      await picker.updateComplete

      const select = picker.shadowRoot?.querySelector('md-outlined-select')
      assert.equal(select?.getAttribute('aria-invalid'), 'true')
    })

    it('should have aria-describedby when supporting text is present', async () => {
      picker.supportingText = 'Choose your preferred currency'
      await picker.updateComplete

      const select = picker.shadowRoot?.querySelector('md-outlined-select')
      assert.exists(select?.getAttribute('aria-describedby'))
    })
  })

  describe('Multi-select ARIA', () => {
    let picker: CurrencyPicker

    beforeEach(async () => {
      picker = await multiSelectFixture()
    })

    it('should announce selection count for multi-select', async () => {
      picker.selected = ['USD', 'EUR', 'GBP']
      await picker.updateComplete

      const container = picker.shadowRoot?.querySelector('.currency-picker')
      const ariaLabel = container?.getAttribute('aria-label')

      assert.include(ariaLabel || '', '3 currencies selected')
    })

    it('should have removable chips with proper labels', async () => {
      picker.selected = ['USD', 'EUR']
      await picker.updateComplete

      const chips = picker.shadowRoot?.querySelectorAll('ui-chip[removable]')
      assert.equal(chips?.length, 2)

      chips?.forEach((chip) => {
        assert.isTrue(chip.hasAttribute('removable'))
      })
    })
  })

  describe('Error Announcements', () => {
    let picker: CurrencyPicker

    beforeEach(async () => {
      picker = await errorStateFixture()
    })

    it('should have error alerts with proper ARIA', async () => {
      // Set a value first, then clear to trigger validation
      picker.selected = ['USD']
      await picker.updateComplete

      // Now set to empty to trigger validation error
      picker.selected = []
      await picker.updateComplete

      const errorElement = picker.shadowRoot?.querySelector('.error')
      assert.equal(errorElement?.getAttribute('role'), 'alert')
      assert.equal(errorElement?.getAttribute('aria-live'), 'polite')
    })

    it('should announce errors to screen readers', async () => {
      picker.showErrors = true

      // Set a value first, then clear to trigger validation
      picker.selected = ['USD']
      await picker.updateComplete

      // Now set to empty to trigger validation error
      picker.selected = []
      await picker.updateComplete

      const errorMessage = picker.shadowRoot?.querySelector('.error-message')
      assert.exists(errorMessage)
      assert.exists(errorMessage?.textContent)
    })
  })

  describe('Keyboard Navigation', () => {
    let picker: CurrencyPicker

    beforeEach(async () => {
      picker = await basicFixture()
    })

    it('should be focusable', async () => {
      const select = picker.shadowRoot?.querySelector('md-outlined-select') as HTMLElement
      select.focus()

      // Check if the picker or its select element has focus
      const activeElement = picker.shadowRoot?.activeElement || document.activeElement
      assert.isTrue(activeElement === select || activeElement === picker)
    })

    it('should support keyboard selection', async () => {
      const select = picker.shadowRoot?.querySelector('md-outlined-select') as HTMLElement
      select.focus()

      // Simulate opening dropdown and selecting
      await sendKeys({
        press: 'Space',
      })

      await sendKeys({
        press: 'ArrowDown',
      })

      await sendKeys({
        press: 'Enter',
      })

      // Should have some interaction (exact behavior depends on md-outlined-select)
      assert.exists(select)
    })

    it('should support chip removal via keyboard in multi-select', async () => {
      picker.multi = true
      picker.selected = ['USD', 'EUR']
      await picker.updateComplete

      const chips = picker.shadowRoot?.querySelectorAll('ui-chip') as NodeListOf<HTMLElement>
      assert.isAtLeast(chips.length, 1)

      // Focus first chip and simulate removal
      chips[0].focus()
      await sendKeys({
        press: 'Delete',
      })

      // The chip should be focusable and support keyboard interaction
      assert.exists(chips[0])
    })
  })

  describe('Focus Management', () => {
    let picker: CurrencyPicker

    beforeEach(async () => {
      picker = await basicFixture()
    })

    it('should have visible focus indicators', async () => {
      const select = picker.shadowRoot?.querySelector('md-outlined-select') as HTMLElement
      select.focus()

      // Check that focus styles are applied (this may require checking computed styles)
      assert.exists(select)
    })

    it('should maintain focus appropriately after interactions', async () => {
      picker.multi = true
      picker.selected = ['USD']
      await picker.updateComplete

      const select = picker.shadowRoot?.querySelector('md-outlined-select') as HTMLElement
      select.focus()

      // Simulate adding another currency
      picker.selected = ['USD', 'EUR']
      await picker.updateComplete

      // Focus should still be manageable
      assert.exists(select)
    })
  })

  describe('Color Contrast and Visual Accessibility', () => {
    let picker: CurrencyPicker

    beforeEach(async () => {
      picker = await basicFixture()
    })

    it('should render with proper contrast for text', async () => {
      // This test would ideally check computed styles for contrast ratios
      const select = picker.shadowRoot?.querySelector('md-outlined-select')
      assert.exists(select)

      // Basic check that text content is rendered
      const options = picker.shadowRoot?.querySelectorAll('md-select-option')
      assert.isAtLeast(options?.length || 0, 1)
    })

    it('should have distinguishable error states', async () => {
      picker.required = true
      picker.showErrors = true
      picker.clearSelection()
      await picker.updateComplete

      const errorElement = picker.shadowRoot?.querySelector('.error')
      const selectElement = picker.shadowRoot?.querySelector('md-outlined-select')
      const isInvalid = !picker.validity.valid
      const hasAriaInvalid = selectElement?.getAttribute('aria-invalid') === 'true'

      assert.exists(errorElement, 'Error element should be present for visual accessibility')
      assert.isTrue(isInvalid, 'Component should be in invalid state')
      assert.isTrue(hasAriaInvalid, 'Select should have aria-invalid=true for screen readers')
    })
  })

  describe('Screen Reader Support', () => {
    let picker: CurrencyPicker

    beforeEach(async () => {
      picker = await basicFixture()
    })

    it('should have proper semantic structure', async () => {
      // Check that component has accessible structure
      const container = picker.shadowRoot?.querySelector('.currency-picker')
      const select = picker.shadowRoot?.querySelector('md-outlined-select')

      assert.exists(container)
      assert.equal(container?.getAttribute('role'), 'group')
      assert.exists(container?.getAttribute('aria-label'))
      assert.exists(select)
    })

    it('should announce state changes', async () => {
      picker.selected = ['USD']
      await picker.updateComplete

      // Check that ARIA live regions and labels are updated
      const container = picker.shadowRoot?.querySelector('.currency-picker')
      const ariaLabel = container?.getAttribute('aria-label')

      assert.include(ariaLabel || '', 'selected')
    })
  })

  describe('WCAG Compliance', () => {
    let picker: CurrencyPicker

    beforeEach(async () => {
      picker = await basicFixture()
    })

    it('should have sufficient touch targets', async () => {
      // Check that interactive elements are large enough for touch
      const select = picker.shadowRoot?.querySelector('md-outlined-select')
      assert.exists(select)

      // Material Design select should have proper touch targets
      // This would ideally check computed dimensions
    })

    it('should work without JavaScript enhancements', async () => {
      // Basic HTML structure should be accessible
      const select = picker.shadowRoot?.querySelector('md-outlined-select')
      const options = picker.shadowRoot?.querySelectorAll('md-select-option')

      assert.exists(select)
      assert.isAtLeast(options?.length || 0, 1)
    })

    it('should support high contrast mode', async () => {
      // This would check forced-colors media query support
      // For now, verify basic structure exists
      const container = picker.shadowRoot?.querySelector('.currency-picker')
      assert.exists(container)
    })

    it('should respect reduced motion preferences', async () => {
      // This would check prefers-reduced-motion media query
      // For now, verify component doesn't rely on motion for function
      picker.selected = ['USD']
      await picker.updateComplete

      assert.deepEqual(picker.selected, ['USD'])
    })
  })
})
