import '@testing-library/jest-dom'

import { render, screen } from '@testing-library/react'

import { IPktDatepicker, PktDatepicker } from './Datepicker'

const datePickerId = 'datepickerId'
const label = 'Date Picker Label'

const createDatepickerTest = (props: Partial<IPktDatepicker> = {}) => {
  const defaultProps: IPktDatepicker = {
    label,
    id: datePickerId,
    ...props,
  }

  return render(<PktDatepicker {...defaultProps} />)
}

describe('PktDatepicker', () => {
  describe('Rendering and basic functionality', () => {
    test('renders without errors', () => {
      const { container } = createDatepickerTest()

      expect(container.querySelector('.pkt-datepicker')).toBeInTheDocument()
    })

    test('renders with correct structure', () => {
      const { container } = createDatepickerTest()

      const inputWrapper = container.querySelector('.pkt-inputwrapper')
      expect(inputWrapper).toBeInTheDocument()

      const input = container.querySelector('input[type="date"]')
      expect(input).toBeInTheDocument()

      const button = container.querySelector('button[type="button"]')
      expect(button).toBeInTheDocument()

      const popup = container.querySelector('.pkt-calendar-popup')
      expect(popup).toBeInTheDocument()
      expect(popup).toHaveAttribute('hidden')
    })

    test('renders pkt-datepicker class on outer wrapper', () => {
      const { container } = createDatepickerTest()

      const outer = container.querySelector('.pkt-datepicker')
      expect(outer).toBeInTheDocument()
    })

    test.each([
      ['small', 'small'],
      ['xsmall', 'xsmall'],
    ] as const)('applies inputSize="%s" classes on root, input and calendar button', (size, sizeClass) => {
      const { container } = createDatepickerTest({ inputSize: size })

      expect(container.querySelector(`.pkt-datepicker--${sizeClass}`)).toBeTruthy()
      expect(container.querySelector(`.pkt-input--${sizeClass}`)).toBeTruthy()
      expect(container.querySelector(`.pkt-btn--${sizeClass}`)).toBeTruthy()
    })

    test('renders datepicker inputs container', () => {
      const { container } = createDatepickerTest()

      const inputs = container.querySelector('.pkt-datepicker__inputs')
      expect(inputs).toBeInTheDocument()
    })

    test('renders calendar button with icon', () => {
      const { container } = createDatepickerTest()

      const button = container.querySelector('button[type="button"]')
      expect(button).toBeInTheDocument()
      expect(button).toHaveAttribute('aria-label', 'Åpne kalender')
    })
  })

  describe('Properties and attributes', () => {
    test('applies default properties correctly', () => {
      const { container } = createDatepickerTest()

      const input = container.querySelector('input[type="date"]') as HTMLInputElement
      expect(input).toBeInTheDocument()
      expect(input.value).toBe('')
      expect(input).not.toBeDisabled()
      expect(input).not.toBeRequired()
    })

    test('handles value property correctly', () => {
      const { container } = createDatepickerTest({
        value: '2024-06-15',
      })

      const input = container.querySelector('input[type="date"]') as HTMLInputElement
      expect(input.value).toBe('2024-06-15')
    })

    test('handles multiple values correctly', () => {
      const { container } = createDatepickerTest({
        multiple: true,
        value: ['2024-06-15', '2024-06-20', '2024-06-25'],
      })

      const tags = container.querySelectorAll('.pkt-date-tags .pkt-tag')
      expect(tags.length).toBe(3)
    })

    test('handles range values correctly', () => {
      const { container } = createDatepickerTest({
        range: true,
        value: ['2024-06-15', '2024-06-25'],
      })

      const inputs = container.querySelectorAll('input[type="date"]') as NodeListOf<HTMLInputElement>
      expect(inputs.length).toBe(2)
      expect(inputs[0].value).toBe('2024-06-15')
      expect(inputs[1].value).toBe('2024-06-25')
    })

    test('handles label property correctly', () => {
      createDatepickerTest({ label: 'Custom Label' })

      expect(screen.getByText('Custom Label')).toBeInTheDocument()
    })

    test('handles maxlength property correctly', () => {
      const { container } = createDatepickerTest({
        multiple: true,
        maxlength: 5,
        value: ['2024-06-15', '2024-06-20'],
      })

      const counter = container.querySelector('.pkt-input__counter')
      expect(counter).toBeInTheDocument()
    })

    test('handles disabled property correctly', () => {
      const { container } = createDatepickerTest({
        disabled: true,
      })

      const input = container.querySelector('input[type="date"]') as HTMLInputElement
      expect(input).toBeDisabled()

      const button = container.querySelector('button[type="button"]')
      expect(button).toBeDisabled()
    })

    test('handles required attribute', () => {
      const { container } = createDatepickerTest({
        required: true,
      })

      const input = container.querySelector('input[type="date"]') as HTMLInputElement
      expect(input).toBeRequired()
    })

    test('sets min and max date boundaries on input', () => {
      const { container } = createDatepickerTest({
        min: '2024-01-01',
        max: '2024-12-31',
        value: '2024-06-15',
      })

      const input = container.querySelector('input[type="date"]') as HTMLInputElement
      expect(input).toHaveAttribute('min', '2024-01-01')
      expect(input).toHaveAttribute('max', '2024-12-31')
    })

    test('sets min and max on both range inputs', () => {
      const { container } = createDatepickerTest({
        range: true,
        min: '2024-01-01',
        max: '2024-12-31',
      })

      const inputs = container.querySelectorAll('input[type="date"]') as NodeListOf<HTMLInputElement>
      expect(inputs[0]).toHaveAttribute('min', '2024-01-01')
      expect(inputs[0]).toHaveAttribute('max', '2024-12-31')
      expect(inputs[1]).toHaveAttribute('min', '2024-01-01')
      expect(inputs[1]).toHaveAttribute('max', '2024-12-31')
    })

    test('renders placeholder text correctly', () => {
      const { container } = createDatepickerTest({
        placeholder: 'dd.mm.yyyy',
      })

      const input = container.querySelector('input[type="date"]') as HTMLInputElement
      expect(input).toHaveAttribute('placeholder', 'dd.mm.yyyy')
    })

    test('renders with custom className', () => {
      const { container } = createDatepickerTest({
        className: 'my-custom-class',
      })

      const wrapper = container.querySelector('.pkt-datepicker')
      expect(wrapper).toHaveClass('my-custom-class')
    })

    test('uses id for input name when no name specified', () => {
      const { container } = createDatepickerTest()

      const input = container.querySelector('input[type="date"]') as HTMLInputElement
      expect(input).toHaveAttribute('name', datePickerId)
    })

    test('uses custom name when specified', () => {
      const { container } = createDatepickerTest({
        name: 'dateField',
        value: '2024-06-15',
      })

      const formInput = container.querySelector('input[aria-hidden="true"]') as HTMLInputElement
      expect(formInput).toHaveAttribute('name', 'dateField')
      expect(formInput.value).toBe('2024-06-15')
    })
  })

  describe('Calendar integration', () => {
    test('renders calendar popup hidden by default', () => {
      const { container } = createDatepickerTest()

      const popup = container.querySelector('.pkt-calendar-popup')
      expect(popup).toHaveAttribute('hidden')
      expect(popup).toHaveClass('hide')
    })

    test('renders calendar inside popup', () => {
      const { container } = createDatepickerTest({ calendarOpen: true })

      const calendar = container.querySelector('.pkt-calendar')
      expect(calendar).toBeInTheDocument()
    })

    test('passes min/max to calendar component', () => {
      const { container } = createDatepickerTest({
        calendarOpen: true,
        min: '2024-01-01',
        max: '2024-12-31',
      })

      const calendar = container.querySelector('.pkt-calendar') as HTMLElement
      expect(calendar).toBeInTheDocument()

      const input = container.querySelector('input[type="date"]') as HTMLInputElement
      expect(input).toHaveAttribute('min', '2024-01-01')
      expect(input).toHaveAttribute('max', '2024-12-31')
    })

    test('passes weeknumbers to calendar', () => {
      const { container } = createDatepickerTest({
        calendarOpen: true,
        weeknumbers: true,
      })

      const calendar = container.querySelector('.pkt-calendar') as HTMLElement
      expect(calendar).toBeInTheDocument()
    })

    test('passes multiple and range to calendar', () => {
      const { container: multipleContainer } = createDatepickerTest({
        calendarOpen: true,
        multiple: true,
      })

      const multiCal = multipleContainer.querySelector('.pkt-calendar') as HTMLElement
      expect(multiCal).toBeInTheDocument()

      const { container: rangeContainer } = createDatepickerTest({
        calendarOpen: true,
        range: true,
      })

      const rangeCal = rangeContainer.querySelector('.pkt-calendar') as HTMLElement
      expect(rangeCal).toBeInTheDocument()
    })
  })
})
