import '@testing-library/jest-dom'

import { act, render } from '@testing-library/react'
import { axe, toHaveNoViolations } from 'jest-axe'
import { vi } from 'vitest'

import { PktLoader } from './Loader'
expect.extend(toHaveNoViolations)

describe('PktLoader', () => {
  describe('basic rendering', () => {
    it('renders correctly without any props', () => {
      const { container } = render(<PktLoader id="loader1" />)

      const root = container.querySelector('.pkt-loader')
      expect(root).toBeInTheDocument()
      expect(root).toHaveAttribute('id', 'loader1')
      expect(root).toHaveAttribute('role', 'status')
      expect(root).toHaveAttribute('aria-busy', 'true')
    })

    it('renders with size and variant', () => {
      const { container } = render(
        <PktLoader id="loader1" size="small" variant="rainbow" message="Loading.." />,
      )

      const root = container.querySelector('.pkt-loader')
      expect(root).toHaveClass('pkt-loader--small')
      expect(root?.querySelector('.pkt-loader__spinner')).toBeInTheDocument()
      expect(root).toHaveTextContent('Loading..')
    })

    it('renders inline', () => {
      const { container } = render(<PktLoader size="medium" message="Loading.." inline />)
      expect(container.querySelector('.pkt-loader--inline')).toBeInTheDocument()
    })

    it('hides children while loading and shows them when not loading', () => {
      const { container, rerender } = render(
        <PktLoader isLoading>
          <span data-testid="child">Innhold</span>
        </PktLoader>,
      )

      const slot = container.querySelector('.pkt-contents')
      expect(slot).toHaveClass('pkt-hide')
      expect(slot?.querySelector('[data-testid="child"]')).toBeInTheDocument()

      rerender(
        <PktLoader isLoading={false}>
          <span data-testid="child">Innhold</span>
        </PktLoader>,
      )
      expect(container.querySelector('.pkt-contents')).not.toHaveClass('pkt-hide')
      expect(container.querySelector('.pkt-loader__spinner')).not.toBeInTheDocument()
    })
  })

  describe('delay', () => {
    it('defers the spinner until after the delay has elapsed', () => {
      vi.useFakeTimers()
      try {
        const { container } = render(<PktLoader delay={500} />)
        expect(container.querySelector('.pkt-loader__spinner')).not.toBeInTheDocument()

        act(() => {
          vi.advanceTimersByTime(500)
        })
        expect(container.querySelector('.pkt-loader__spinner')).toBeInTheDocument()
      } finally {
        vi.useRealTimers()
      }
    })
  })

  describe('accessibility', () => {
    it('renders with no wcag errors with axe', async () => {
      const { container } = render(<PktLoader message="Loading.." variant="shapes" size="small" />)
      const results = await axe(container)
      expect(results).toHaveNoViolations()
    })
  })
})
