import '@testing-library/jest-dom'
import { render, fireEvent } from '@testing-library/react'
import { parseISODateString } from 'shared-utils/date-utils'

import { PktCalendar, IPktCalendar } from './Calendar'

const createCalendar = (props: Partial<IPktCalendar> = {}) => {
  return render(<PktCalendar {...props} />)
}

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

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

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

      const calendarElement = container.querySelector('.pkt-calendar')
      const calendarTable = container.querySelector('.pkt-cal-days')
      const monthNav = container.querySelector('.pkt-cal-month-nav')

      expect(calendarElement).toBeInTheDocument()
      expect(calendarTable).toBeInTheDocument()
      expect(monthNav).toBeInTheDocument()
    })

    test('renders month picker when withcontrols is true', () => {
      const { container } = createCalendar({ withcontrols: true })

      // Navigation buttons should always be present
      const prevButton = container.querySelector('.pkt-calendar__prev-month')
      const nextButton = container.querySelector('.pkt-calendar__next-month')
      expect(prevButton).toBeInTheDocument()
      expect(nextButton).toBeInTheDocument()

      // Should show month picker controls, not static title
      const monthPicker = container.querySelector('.pkt-cal-month-picker')
      const monthTitle = container.querySelector('.pkt-calendar__month-title')

      expect(monthPicker).toBeInTheDocument()
      expect(monthTitle).not.toBeInTheDocument()

      // Should have month and year inputs
      const monthSelect = monthPicker?.querySelector('select')
      const yearInput = monthPicker?.querySelector('input[type="number"]')
      expect(monthSelect).toBeInTheDocument()
      expect(yearInput).toBeInTheDocument()
    })

    test('renders static month title when withcontrols is false', () => {
      const { container } = createCalendar()

      // Navigation buttons should always be present
      const prevButton = container.querySelector('.pkt-calendar__prev-month')
      const nextButton = container.querySelector('.pkt-calendar__next-month')
      expect(prevButton).toBeInTheDocument()
      expect(nextButton).toBeInTheDocument()

      // Should show static month title, not controls
      const monthTitle = container.querySelector('.pkt-calendar__month-title')
      const monthPicker = container.querySelector('.pkt-cal-month-picker')

      expect(monthTitle).toBeInTheDocument()
      expect(monthPicker).not.toBeInTheDocument()
    })
  })

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

      // Verify defaults through DOM effects
      const grid = container.querySelector('[role="grid"]')
      expect(grid).not.toHaveAttribute('aria-multiselectable')

      // No week numbers by default
      const weekNumbers = container.querySelectorAll('.pkt-calendar__week-number')
      expect(weekNumbers.length).toBe(0)

      // No month picker by default
      const monthPicker = container.querySelector('.pkt-cal-month-picker')
      expect(monthPicker).not.toBeInTheDocument()

      // No selected dates
      const selectedDates = container.querySelectorAll('.pkt-calendar__date--selected')
      expect(selectedDates.length).toBe(0)
    })

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

      const grid = container.querySelector('[role="grid"]')
      expect(grid).toHaveAttribute('aria-multiselectable', 'true')
    })

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

      const grid = container.querySelector('[role="grid"]')
      expect(grid).toHaveAttribute('aria-multiselectable', 'true')
    })

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

      const weekNumbers = container.querySelectorAll('.pkt-calendar__week-number')
      expect(weekNumbers.length).toBeGreaterThan(0)
    })

    test('handles maxMultiple property correctly', () => {
      const { container } = createCalendar({ multiple: true, maxMultiple: 3 })

      const grid = container.querySelector('[role="grid"]')
      expect(grid).toHaveAttribute('aria-multiselectable', 'true')

      // Select 3 dates - all should work
      const availableDates = container.querySelectorAll(
        '.pkt-calendar__date:not(.pkt-calendar__date--disabled)',
      )
      expect(availableDates.length).toBeGreaterThan(3)

      fireEvent.click(availableDates[0])
      fireEvent.click(availableDates[1])
      fireEvent.click(availableDates[2])

      const selectedDates = container.querySelectorAll('.pkt-calendar__date--selected')
      expect(selectedDates.length).toBe(3)
    })

    test('handles currentmonth property correctly', () => {
      const { container } = createCalendar({ currentmonth: '2024-03-15' })

      const monthTitle = container.querySelector('.pkt-calendar__month-title')
      expect(monthTitle?.textContent).toContain('Mars')
      expect(monthTitle?.textContent).toContain('2024')
    })
  })

  describe('Month navigation', () => {
    it('should navigate to previous month when clicking previous button', () => {
      const { container } = createCalendar({ currentmonth: '2024-06-15' })

      const monthTitle = container.querySelector('.pkt-calendar__month-title')
      expect(monthTitle?.textContent).toContain('Juni')

      const prevButton = container.querySelector('.pkt-calendar__prev-month')
      fireEvent.click(prevButton!)

      expect(monthTitle?.textContent).toContain('Mai')
    })

    it('should navigate to next month when clicking next button', () => {
      const { container } = createCalendar({ currentmonth: '2024-06-15' })

      const monthTitle = container.querySelector('.pkt-calendar__month-title')
      expect(monthTitle?.textContent).toContain('Juni')

      const nextButton = container.querySelector('.pkt-calendar__next-month')
      fireEvent.click(nextButton!)

      expect(monthTitle?.textContent).toContain('Juli')
    })

    test('navigates to next month with controls', () => {
      const { container } = createCalendar({ withcontrols: true, currentmonth: '2024-06-15' })

      const nextButton = container.querySelector('.pkt-calendar__next-month')
      expect(nextButton).toBeInTheDocument()

      const monthSelect = container.querySelector(
        '.pkt-cal-month-picker select',
      ) as HTMLSelectElement
      const initialMonth = monthSelect?.value

      fireEvent.click(nextButton!)

      const newMonth = monthSelect?.value
      expect(newMonth).not.toBe(initialMonth)
    })

    test('month navigation updates visible dates', () => {
      const { container } = createCalendar({ withcontrols: true, currentmonth: '2024-06-15' })

      const initialDates = Array.from(container.querySelectorAll('.pkt-calendar__date')).map(
        (el) => el.textContent,
      )

      const nextButton = container.querySelector('.pkt-calendar__next-month')
      fireEvent.click(nextButton!)

      const newDates = Array.from(container.querySelectorAll('.pkt-calendar__date')).map(
        (el) => el.textContent,
      )
      expect(newDates).not.toEqual(initialDates)
    })
  })

  describe('Date formatting and localization', () => {
    test('displays day names correctly', () => {
      const { container } = createCalendar()

      const dayHeaders = container.querySelectorAll('.pkt-calendar__day-name')
      expect(dayHeaders.length).toBe(7)

      dayHeaders.forEach((header) => {
        expect(header.textContent).toBeTruthy()
        expect(header.textContent!.length).toBeGreaterThan(0)
      })
    })

    test('displays month names correctly', () => {
      const { container } = createCalendar({ currentmonth: '2024-06-15' })

      const monthTitle = container.querySelector('.pkt-calendar__month-title')
      expect(monthTitle).toBeInTheDocument()
      expect(monthTitle?.textContent).toBeTruthy()
    })

    test('handles custom day strings', () => {
      const { container } = createCalendar({
        strings: { daysShort: ['S', 'M', 'T', 'W', 'T', 'F', 'S'] },
      })

      const dayHeaders = container.querySelectorAll('.pkt-calendar__day-name')
      expect(dayHeaders[0].textContent?.trim()).toBe('S')
      expect(dayHeaders[1].textContent?.trim()).toBe('M')
    })

    test('handles custom month strings', () => {
      const { container } = createCalendar({
        withcontrols: true,
        strings: {
          months: [
            'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
            'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',
          ],
        },
      })

      const monthSelect = container.querySelector('.pkt-cal-month-picker select')
      expect(monthSelect).toBeInTheDocument()

      const options = monthSelect?.querySelectorAll('option')
      expect(options?.[0]?.textContent).toContain('Jan')
    })
  })

  describe('Today highlighting', () => {
    test('highlights today date', () => {
      const { container } = createCalendar()

      const todayDate = container.querySelector('.pkt-calendar__date--today')
      expect(todayDate).toBeInTheDocument()
    })

    test('today date is selectable unless excluded', () => {
      const { container } = createCalendar()

      const todayDate = container.querySelector('.pkt-calendar__date--today')

      if (todayDate && !todayDate.classList.contains('pkt-calendar__date--disabled')) {
        fireEvent.click(todayDate)
        expect(todayDate).toHaveClass('pkt-calendar__date--selected')
      }
    })
  })
})
