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

import Accordion from './Accordion'
import Button from '../Button/Button'

describe('Accordion', () => {
  const defaultProps = {
    title: 'Test Accordion',
    children: <div>Accordion Content</div>,
  }

  it('renders with basic props', () => {
    render(<Accordion {...defaultProps} />)

    expect(screen.getByTestId('accordion-container')).toBeInTheDocument()
    const accordionTitle = screen.getByTestId('accordion-title')
    expect(accordionTitle).toBeInTheDocument()
    expect(accordionTitle).toHaveTextContent('Test Accordion')

    const accordionContent = screen.getByTestId('accordion-content')
    expect(accordionContent).toBeInTheDocument()
    expect(accordionContent).toHaveTextContent('Accordion Content')
  })

  it('renders with subtitle', () => {
    const subtitle = 'Test Subtitle'
    render(<Accordion {...defaultProps} subtitle={subtitle} />)

    const accordionSubtitle = screen.getByTestId('accordion-subtitle')
    expect(accordionSubtitle).toBeInTheDocument()
    expect(accordionSubtitle).toHaveTextContent('Test Subtitle')
  })

  it('renders with actions', () => {
    const actions = <Button variant='secondary'>Test Action</Button>
    render(<Accordion {...defaultProps} actions={actions} />)

    expect(screen.getByTestId('accordion-actions')).toBeInTheDocument()
    expect(
      screen.getByRole('button', { name: 'Test Action' }),
    ).toBeInTheDocument()
  })

  it('renders with caret text instead of icon', () => {
    const caretText = 'Click to expand'
    render(<Accordion {...defaultProps} caretText={caretText} />)

    expect(screen.getByTestId('accordion-caret-text')).toBeInTheDocument()
    expect(screen.getByText(caretText)).toBeInTheDocument()
  })

  it('renders with icon when no caret text is provided', () => {
    render(<Accordion {...defaultProps} />)

    const icon = screen.getByTestId('icon-caretDown')
    expect(icon).toBeInTheDocument()
  })

  it('toggles content visibility when clicked', () => {
    render(<Accordion {...defaultProps} />)

    const header = screen.getByTestId('accordion-header')
    const container = screen.getByTestId('accordion-container')

    expect(container).not.toHaveClass('isOpen')

    fireEvent.click(header)
    expect(container).toHaveClass('isOpen')

    fireEvent.click(header)
    expect(container).not.toHaveClass('isOpen')
  })

  it('calls callout function when toggled', () => {
    const callout = vi.fn<(isExpanded: boolean) => void>()
    render(<Accordion {...defaultProps} callout={callout} />)

    const header = screen.getByTestId('accordion-header')

    fireEvent.click(header)
    expect(callout).toHaveBeenCalledWith(true)

    fireEvent.click(header)
    expect(callout).toHaveBeenCalledWith(false)
  })

  it('does not toggle when disabled', () => {
    const callout = vi.fn<(isExpanded: boolean) => void>()
    render(<Accordion {...defaultProps} disabled callout={callout} />)

    const header = screen.getByTestId('accordion-header')
    const container = screen.getByTestId('accordion-container')

    fireEvent.click(header)
    expect(container).not.toHaveClass('isOpen')
    expect(container).toHaveClass('disabled')
    expect(callout).not.toHaveBeenCalled()
  })

  it('renders in expanded state when isExpanded is true', () => {
    render(<Accordion {...defaultProps} isExpanded />)

    const container = screen.getByTestId('accordion-container')
    expect(container).toHaveClass('isOpen')
  })

  it('renders with custom background color', () => {
    render(<Accordion {...defaultProps} backgroundColor='faint-gray' />)

    const container = screen.getByTestId('accordion-container')
    expect(container).toHaveStyle({ backgroundColor: 'var(--faint-gray)' })
  })

  it('renders checkbox in checked state when checked prop is true', () => {
    render(<Accordion {...defaultProps} checked />)

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

  it('prevents action click from toggling accordion', () => {
    const actionClick = vi.fn<() => void>()
    const actions = <Button onClick={actionClick}>Test Action</Button>
    render(<Accordion {...defaultProps} actions={actions} />)

    const actionButton = screen.getByRole('button', { name: 'Test Action' })
    fireEvent.click(actionButton)

    expect(actionClick).toHaveBeenCalled()

    const container = screen.getByTestId('accordion-container')
    expect(container).not.toHaveClass('isOpen')
  })
})
