import '@testing-library/jest-dom'
import { axe, toHaveNoViolations } from 'jest-axe'
import { fireEvent } from '@testing-library/dom'
import { createElementTest, BaseTestConfig } from '../../tests/test-framework'
import { CustomElementFor } from '../../tests/component-registry'
import './calendar'

expect.extend(toHaveNoViolations)

export interface CalendarTestConfig extends BaseTestConfig {
  withcontrols?: boolean
  weeknumbers?: boolean
  multiple?: boolean
  range?: boolean
  earliest?: string
  latest?: string
  currentmonth?: string
  excludedates?: string
  excludeweekdays?: string
}

// Use shared framework
export const createCalendarTest = async (config: CalendarTestConfig = {}) => {
  const { container, element } = await createElementTest<
    CustomElementFor<'pkt-calendar'>,
    CalendarTestConfig
  >('pkt-calendar', config)

  return {
    container,
    calendar: element,
  }
}

describe('PktCalendar', () => {
  describe('Accessibility', () => {
    test('has no accessibility violations', async () => {
      const { calendar } = await createCalendarTest({ withcontrols: true, weeknumbers: true })

      const results = await axe(calendar)
      expect(results).toHaveNoViolations()
    })

    test('has proper ARIA attributes', async () => {
      const { calendar } = await createCalendarTest({ withcontrols: true })

      const calendarTable = calendar.querySelector('.pkt-calendar__body')
      expect(calendarTable).toHaveAttribute('role', 'grid')

      const dateButtons = calendar.querySelectorAll('.pkt-calendar__date')
      dateButtons.forEach((button) => {
        expect(button).toHaveAttribute('aria-pressed')
        expect(button).toHaveAttribute('tabindex')
      })
    })

    test('navigation buttons have proper labels', async () => {
      const { calendar } = await createCalendarTest({ withcontrols: true })

      const prevButton = calendar.querySelector('.pkt-calendar__prev-month')
      const nextButton = calendar.querySelector('.pkt-calendar__next-month')

      expect(prevButton).toHaveAttribute('aria-label')
      expect(nextButton).toHaveAttribute('aria-label')
    })

    test('date buttons have proper accessible names', async () => {
      const { calendar } = await createCalendarTest()

      const dateButtons = calendar.querySelectorAll('.pkt-calendar__date')
      dateButtons.forEach((button) => {
        expect(button).toHaveAttribute('aria-label')
        expect(button.getAttribute('aria-label')).toBeTruthy()
      })
    })

    test('selected dates have proper ARIA state', async () => {
      const { calendar } = await createCalendarTest()

      const firstDate = calendar.querySelector(
        '.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
      )
      fireEvent.click(firstDate!)
      await calendar.updateComplete

      expect(firstDate).toHaveAttribute('aria-pressed', 'true')
    })

    test('disabled dates have proper ARIA state', async () => {
      const { calendar } = await createCalendarTest({ excludeweekdays: '0,6' })

      const disabledDates = calendar.querySelectorAll('.pkt-calendar__date--disabled')
      disabledDates.forEach((date) => {
        expect(date).toHaveAttribute('disabled')
      })
    })
  })
})
