import '@testing-library/jest-dom'

import { render, screen } from '@testing-library/react'
import { axe, toHaveNoViolations } from 'jest-axe'
import { createRef } from 'react'

import { PktProgressbar } from './Progressbar'

expect.extend(toHaveNoViolations)

describe('PktProgressbar', () => {
  describe('rendering', () => {
    test('renders with default props', () => {
      const { container } = render(<PktProgressbar id="progress1" valueCurrent={50} />)

      const progressbar = container.firstChild as HTMLElement

      expect(progressbar).toBeInTheDocument()
      expect(progressbar).toHaveAttribute('id', 'progress1')
      expect(progressbar).toHaveAttribute('aria-valuemin', '0')
      expect(progressbar).toHaveAttribute('aria-valuemax', '100')
      expect(progressbar).toHaveAttribute('aria-valuenow', '50')

      const bar = progressbar?.querySelector('.pkt-progressbar__bar--dark-blue')
      expect(bar).toBeInTheDocument()
    })

    test('renders with custom skin', () => {
      const { container } = render(<PktProgressbar id="progress2" valueCurrent={50} skin="red" />)

      const progressbar = container.firstChild as HTMLElement
      const bar = progressbar?.querySelector('.pkt-progressbar__bar--red')
      expect(bar).toBeInTheDocument()
    })

    test('renders title correctly', () => {
      const { container, getByText } = render(
        <PktProgressbar id="progress3" valueCurrent={50} title="Progress" />,
      )

      const progressbar = container.firstChild as HTMLElement

      const title = progressbar?.querySelector('.pkt-progressbar__title')
      expect(title).toBeInTheDocument()

      const titleText = getByText('Progress')
      expect(titleText).toBeInTheDocument()
    })

    test('renders title with center position', () => {
      const { container } = render(
        <PktProgressbar id="progress4" valueCurrent={50} title="Progress" titlePosition="center" />,
      )
      const title = container.querySelector('.pkt-progressbar__title-center')
      expect(title).toBeInTheDocument()
    })

    test('renders status as percentage', () => {
      const { container } = render(
        <PktProgressbar id="progress5" valueCurrent={50} statusType="percentage" />,
      )
      const status = container.querySelector('.pkt-progressbar__status')
      expect(status).toBeInTheDocument()
      expect(status).toHaveTextContent('50%')
    })

    test('renders status as fraction', () => {
      const { container } = render(
        <PktProgressbar id="progress6" valueCurrent={50} valueMax={200} statusType="fraction" />,
      )
      const status = container.querySelector('.pkt-progressbar__status')
      expect(status).toBeInTheDocument()
      expect(status).toHaveTextContent('50 av 200')
    })

    test('renders status with center placement', () => {
      const { container } = render(
        <PktProgressbar
          id="progress7"
          valueCurrent={50}
          statusType="percentage"
          statusPlacement="center"
        />,
      )
      const status = container.querySelector('.pkt-progressbar__status--center')
      expect(status).toBeInTheDocument()
    })

    test('renders status with following placement', () => {
      const { container } = render(
        <PktProgressbar
          id="progress8"
          valueCurrent={50}
          statusType="percentage"
          statusPlacement="following"
        />,
      )
      const status = container.querySelector('.pkt-progressbar__status-placement--following')
      expect(status).toBeInTheDocument()
    })

    test('handles aria-label correctly', () => {
      const { container } = render(
        <PktProgressbar id="progress9" valueCurrent={50} ariaLabel="Progress bar" />,
      )
      const progressbar = container.firstChild as HTMLElement
      expect(progressbar).toHaveAttribute('aria-label', 'Progress bar')
      expect(progressbar).not.toHaveAttribute('aria-labelledby')
    })

    test('handles role meter correctly', () => {
      const { container } = render(
        <PktProgressbar id="progress10" role="meter" valueCurrent={50} ariaLabel="Meter bar" />,
      )
      const progressbar = container.firstChild as HTMLElement
      expect(progressbar).toHaveAttribute('role', 'meter')
    })

    test('handles id for title and aria-labelledby correctly', () => {
      const { container } = render(
        <PktProgressbar valueCurrent={50} title="Progress" id="progressId" />,
      )

      const progressbar = container.firstChild as HTMLElement

      expect(progressbar).toBeInTheDocument()
      expect(progressbar).toHaveAttribute('aria-labelledby', 'progressId-title')
    })

    test('generates id if none is provided', () => {
      const { container } = render(<PktProgressbar valueCurrent={50} />)

      const progressbar = container.firstChild as HTMLElement

      const id = progressbar?.getAttribute('id')
      expect(id).toHaveLength(36)
    })

    test('sets ref correctly', () => {
      const ref = createRef<HTMLDivElement>()
      const { unmount } = render(
        <PktProgressbar ref={ref} id="progress-ref" valueCurrent={50} title="Ref bar" />,
      )

      expect(ref.current).toBeInstanceOf(HTMLDivElement)
      unmount()
      expect(ref.current).toBeNull()
    })
  })

  // ACCESSIBILITY TESTS

  describe('accessibility', () => {
    test('renders with no wcag errors with axe', async () => {
      const { container } = render(
        <PktProgressbar id="progress-axe" valueCurrent={50} title="Axe test" role="progressbar" />,
      )
      const results = await axe(container)
      expect(results).toHaveNoViolations()
    })
  })
})
