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

import Checkbox from './Checkbox'

describe('Checkbox Component', () => {
  const defaultProps = {
    label: 'Test Checkbox',
    name: 'test-checkbox',
  }

  it('renders checkbox with label', () => {
    render(<Checkbox {...defaultProps} />)

    const checkbox = screen.getByTestId('checkbox-component')
    const label = screen.getByTestId('checkbox-label')

    expect(checkbox).toBeInTheDocument()
    expect(label).toBeInTheDocument()
    expect(label).toHaveTextContent('Test Checkbox')
  })

  it('handles checked state correctly', () => {
    render(<Checkbox {...defaultProps} checked={true} />)

    const checkbox = screen.getByTestId('checkbox-component')
    const icon = screen.getByTestId('icon-checkNoCircle')
    expect(checkbox).toHaveClass('checked')
    expect(icon).toBeInTheDocument()
  })

  it('handles partial checked state correctly', () => {
    render(<Checkbox {...defaultProps} partialChecked={true} />)

    const checkbox = screen.getByTestId('checkbox-component')
    const icon = screen.getByTestId('icon-dash')
    expect(checkbox).toHaveClass('partialChecked')
    expect(icon).toBeInTheDocument()
  })

  it('handles disabled state correctly', () => {
    render(<Checkbox {...defaultProps} disabled={true} />)

    const checkbox = screen.getByTestId('checkbox-component')
    expect(checkbox).toHaveClass('disabled')
  })

  it('handles error state correctly', () => {
    render(<Checkbox {...defaultProps} error={true} />)

    const checkbox = screen.getByTestId('checkbox-component')
    expect(checkbox).toHaveClass('error')
  })

  it('calls callout function when clicked', () => {
    const mockCallout =
      vi.fn<
        (
          stateName: string | undefined,
          check: boolean,
          partialChecked?: boolean,
        ) => void
      >()
    render(
      <Checkbox {...defaultProps} stateName='test' callout={mockCallout} />,
    )

    const clickableContainer = screen.getByTestId(
      'checkbox-clickable-container',
    )
    fireEvent.click(clickableContainer)

    expect(mockCallout).toHaveBeenCalledWith('test', true)
  })

  it('handles partial to checked transition correctly', () => {
    const mockCallout =
      vi.fn<
        (
          stateName: string | undefined,
          check: boolean,
          partialChecked?: boolean,
        ) => void
      >()
    render(
      <Checkbox
        {...defaultProps}
        partialChecked={true}
        stateName='test'
        callout={mockCallout}
      />,
    )

    const clickableContainer = screen.getByTestId(
      'checkbox-clickable-container',
    )
    fireEvent.click(clickableContainer)

    expect(mockCallout).toHaveBeenCalledWith('test', false, false)
  })

  it('renders as radio button when type is radio', () => {
    render(<Checkbox {...defaultProps} type='radio' />)

    const checkbox = screen.getByTestId('checkbox-clickable-container')
    expect(checkbox).toHaveClass('radio')
  })

  it('applies custom class names correctly', () => {
    render(
      <Checkbox
        {...defaultProps}
        customClass='custom-class'
        labelClass='custom-label'
      />,
    )

    const checkbox = screen.getByTestId('checkbox-component')
    const label = screen.getByTestId('checkbox-label')

    expect(checkbox).toHaveClass('custom-class')
    expect(label).toHaveClass('custom-label')
  })

  it('hides label when hideLabel prop is true', () => {
    render(<Checkbox {...defaultProps} hideLabel={true} />)

    const label = screen.queryByTestId('checkbox-label')
    expect(label).not.toBeInTheDocument()
  })

  it('handles checkbox color correctly', () => {
    render(<Checkbox {...defaultProps} checkboxColor='blue' />)

    const checkbox = screen.getByTestId('checkbox-clickable-container')
    expect(checkbox).toHaveStyle({ '--checkbox-color': 'var(--blue)' })
  })

  it('handles handleCheck callback when provided', () => {
    const mockHandleCheck =
      vi.fn<
        (
          index: number,
          event: React.MouseEvent<HTMLButtonElement>,
          checked: boolean,
        ) => void
      >()
    render(
      <Checkbox {...defaultProps} index={1} handleCheck={mockHandleCheck} />,
    )

    const clickableContainer = screen.getByTestId(
      'checkbox-clickable-container',
    )
    fireEvent.click(clickableContainer)

    expect(mockHandleCheck).toHaveBeenCalledWith(1, expect.any(Object), false)
  })
})
