import '@testing-library/jest-dom'

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

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('Input field behavior', () => {
    test('allows manual date entry via change event', () => {
      const handleValueChange = vi.fn()
      const { container } = createDatepickerTest({
        onValueChange: handleValueChange,
      })

      const input = container.querySelector('input[type="date"]') as HTMLInputElement
      fireEvent.change(input, { target: { value: '2024-06-15' } })

      expect(handleValueChange).toHaveBeenCalledWith(['2024-06-15'])
    })

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

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

    test('shows help text correctly', () => {
      createDatepickerTest({
        helptext: 'Enter a valid date',
      })

      expect(screen.getByText('Enter a valid date')).toBeInTheDocument()
    })

    test('handles readonly state correctly', () => {
      const { container } = createDatepickerTest({
        readOnly: true,
      })

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

      // Calendar button should still be interactive
      const button = container.querySelector('button[type="button"]')
      expect(button).not.toBeDisabled()
    })

    test('clears value when empty string entered', () => {
      const handleValueChange = vi.fn()
      const { container } = createDatepickerTest({
        value: '2024-06-15',
        onValueChange: handleValueChange,
      })

      const input = container.querySelector('input[type="date"]') as HTMLInputElement
      fireEvent.change(input, { target: { value: '' } })

      expect(handleValueChange).toHaveBeenCalledWith([])
    })

    test('input has correct id based on component id', () => {
      const { container } = createDatepickerTest()

      const input = container.querySelector('input[type="date"]') as HTMLInputElement
      expect(input).toHaveAttribute('id', `${datePickerId}-input`)
    })

    test('range inputs have distinct ids', () => {
      const { container } = createDatepickerTest({
        range: true,
      })

      const fromInput = container.querySelector(`#${datePickerId}-input`)
      const toInput = container.querySelector(`#${datePickerId}-to`)
      expect(fromInput).toBeInTheDocument()
      expect(toInput).toBeInTheDocument()
    })

    test('range inputs have distinct names', () => {
      const { container } = createDatepickerTest({
        range: true,
        name: 'dates',
      })

      const inputs = container.querySelectorAll('input[type="date"]') as NodeListOf<HTMLInputElement>
      expect(inputs[0]).toHaveAttribute('name', 'dates-from')
      expect(inputs[1]).toHaveAttribute('name', 'dates-to')
    })
  })

  describe('Keyboard navigation and interaction', () => {
    test('opens calendar with Space key on single input', () => {
      const { container } = createDatepickerTest()

      const input = container.querySelector('input[type="date"]') as HTMLInputElement
      fireEvent.keyDown(input, { key: ' ' })

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

    test('opens calendar with Space key on range input', () => {
      const { container } = createDatepickerTest({
        range: true,
      })

      const input = container.querySelector('input[type="date"]') as HTMLInputElement
      fireEvent.keyDown(input, { key: ' ' })

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

    test('opens calendar with Space key on multiple input', () => {
      const { container } = createDatepickerTest({
        multiple: true,
      })

      const input = container.querySelector('input[type="date"]') as HTMLInputElement
      fireEvent.keyDown(input, { key: ' ' })

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

    test('closes calendar with Escape key', () => {
      const { container } = createDatepickerTest()

      // Open calendar first
      const button = container.querySelector('button[type="button"]') as HTMLButtonElement
      fireEvent.click(button)

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

      // Close with Escape
      fireEvent.keyDown(document, { key: 'Escape' })

      expect(popup).toHaveAttribute('hidden')
    })

    test('opens calendar when clicking input', () => {
      const { container } = createDatepickerTest()

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

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

    test('does not open calendar when disabled', () => {
      const { container } = createDatepickerTest({
        disabled: true,
      })

      const button = container.querySelector('button[type="button"]') as HTMLButtonElement
      fireEvent.click(button)

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

    test('opens calendar when clicking button', () => {
      const { container } = createDatepickerTest()

      const button = container.querySelector('button[type="button"]') as HTMLButtonElement
      fireEvent.click(button)

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

    test('closes calendar when clicking button again', () => {
      const { container } = createDatepickerTest()

      const button = container.querySelector('button[type="button"]') as HTMLButtonElement
      fireEvent.click(button) // open
      fireEvent.click(button) // close

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

    test('closes calendar when clicking outside', () => {
      const { container } = createDatepickerTest()

      const button = container.querySelector('button[type="button"]') as HTMLButtonElement
      fireEvent.click(button) // open

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

      // Click outside the datepicker
      fireEvent.click(document.body, { bubbles: true })

      expect(popup).toHaveAttribute('hidden')
    })
  })
})
