import '@testing-library/jest-dom'

import './datepicker'
import '../calendar/calendar'
import { PktDatepicker } from './datepicker'

const waitForCustomElements = async () => {
  await customElements.whenDefined('pkt-datepicker')
  await customElements.whenDefined('pkt-calendar')
}

// Helper function to create datepicker markup
const createDatepicker = async (datepickerProps = '') => {
  const container = document.createElement('div')
  container.innerHTML = `
    <pkt-datepicker ${datepickerProps}></pkt-datepicker>
  `
  document.body.appendChild(container)
  await waitForCustomElements()
  return container
}

// Cleanup after each test
afterEach(() => {
  document.body.innerHTML = ''
})

describe('PktDatepicker', () => {
  describe('Date boundary testing', () => {
    test('handles minimum possible dates', async () => {
      const minDate = '1900-01-01'
      const container = await createDatepicker(`value="${minDate}" earliest="${minDate}"`)

      const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
      await datepicker.updateComplete

      expect(datepicker.value).toBe(minDate)
    })

    test('handles maximum possible dates', async () => {
      const maxDate = '2100-12-31'
      const container = await createDatepicker(`value="${maxDate}" latest="${maxDate}"`)

      const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
      await datepicker.updateComplete

      expect(datepicker.value).toBe(maxDate)
    })

    test('handles year boundaries correctly', async () => {
      const yearBoundaryDates = ['1999-12-31', '2000-01-01', '2000-12-31', '2001-01-01']

      for (const date of yearBoundaryDates) {
        const container = await createDatepicker(`value="${date}"`)
        const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
        await datepicker.updateComplete

        expect(datepicker.value).toBe(date)
        container.remove()
      }
    })

    test('handles month boundaries correctly', async () => {
      const monthBoundaryDates = [
        '2024-01-31',
        '2024-02-01',
        '2024-02-28',
        '2024-02-29', // Leap year
        '2024-03-01',
      ]

      for (const date of monthBoundaryDates) {
        const container = await createDatepicker(`value="${date}"`)
        const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
        await datepicker.updateComplete

        expect(datepicker.value).toBe(date)
        container.remove()
      }
    })

    test.each`
      description                                                  | value           | expectedRangeUnderflow | expectedValid
      ${'Test date before min - component should mark it invalid'} | ${'2024-06-05'} | ${true}                | ${false}
      ${'Test date after max - component should mark it invalid'}  | ${'2024-06-25'} | ${false}               | ${false}
      ${'Test valid date - should be accepted and marked valid'}   | ${'2024-06-15'} | ${false}               | ${true}
    `(
      'validates dates against earliest/latest boundaries - $description',
      async ({ value, expectedRangeUnderflow, expectedValid }) => {
        const container = await createDatepicker('min="2024-06-10" max="2024-06-20"')

        const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
        await datepicker.updateComplete

        const input = datepicker.querySelector('input') as HTMLInputElement

        datepicker.value = value
        await datepicker.updateComplete

        expect(datepicker.value).toBe(value)
        expect(input.value).toBe(value)
        expect(datepicker._value).toEqual([value])
        expect(input.validity.rangeUnderflow).toBe(expectedRangeUnderflow)
        expect(input.validity.valid).toBe(expectedValid)
      },
    )
  })

  describe('Error handling and edge cases', () => {
    test('handles invalid date formats gracefully', async () => {
      const container = await createDatepicker('value="not-a-date"')

      const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
      await datepicker.updateComplete

      // Should not crash
      expect(datepicker).toBeInTheDocument()
    })

    test('handles empty values correctly', async () => {
      const container = await createDatepicker('value=""')

      const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
      await datepicker.updateComplete

      expect(datepicker.value).toBe('')
      expect(datepicker.hasError).toBe(false)
    })

    test('handles malformed multiple values', async () => {
      const malformedDates = '2024-06-15,,2024-06-20,,,'
      const container = await createDatepicker(`value="${malformedDates}" multiple`)

      const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
      await datepicker.updateComplete

      // Should filter out empty values
      const tags = datepicker.querySelectorAll('pkt-tag')
      expect(tags.length).toBe(2) // Only valid dates
    })

    test('handles very long value strings', async () => {
      // Create a string with many dates
      const longValueArray = Array.from({ length: 100 }, (_, i) => `2024-06-${(i % 30) + 1}`)
      const longValue = longValueArray.join(',')
      const container = await createDatepicker(`value="${longValue}" multiple maxlength="50"`)

      const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
      await datepicker.updateComplete

      // Should handle gracefully - maxlength may or may not be enforced at render time
      const tags = datepicker.querySelectorAll('pkt-tag')
      expect(tags.length).toBeGreaterThan(0) // Should show some tags
      expect(datepicker).toBeInTheDocument() // Should not crash
    })

    test('handles conflicting properties gracefully', async () => {
      // Both multiple and range shouldn't typically be used together
      const container = await createDatepicker('multiple range value="2024-06-15,2024-06-20"')

      const datepicker = container.querySelector('pkt-datepicker') as PktDatepicker
      await datepicker.updateComplete

      // Should still render without errors
      expect(datepicker).toBeInTheDocument()
    })
  })
})
