import { describe, it, expect, vi, beforeEach } from 'vitest'
import { render, screen, fireEvent } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { Select } from './select'

describe('Select', () => {
  const mockOptions = [
    { value: 'option1', label: 'Option 1' },
    { value: 'option2', label: 'Option 2' },
    { value: 'option3', label: 'Option 3' },
  ]

  const mockOnChange = vi.fn()

  beforeEach(() => {
    vi.clearAllMocks()
  })

  it('should render with placeholder', () => {
    render(
      <Select
        options={mockOptions}
        onValueChange={mockOnChange}
        placeholder="Select an option"
      />
    )

    expect(screen.getByText('Select an option')).toBeInTheDocument()
  })

  it('should open dropdown on click', async () => {
    const user = userEvent.setup()
    
    render(
      <Select
        options={mockOptions}
        onValueChange={mockOnChange}
      />
    )

    const trigger = screen.getByRole('button')
    await user.click(trigger)

    expect(screen.getByText('Option 1')).toBeInTheDocument()
    expect(screen.getByText('Option 2')).toBeInTheDocument()
    expect(screen.getByText('Option 3')).toBeInTheDocument()
  })

  it('should select option and close dropdown', async () => {
    const user = userEvent.setup()
    
    render(
      <Select
        options={mockOptions}
        onValueChange={mockOnChange}
      />
    )

    const trigger = screen.getByRole('button')
    await user.click(trigger)

    await user.click(screen.getByText('Option 2'))

    expect(mockOnChange).toHaveBeenCalledWith('option2')
  })

  it('should display selected value', async () => {
    const user = userEvent.setup()
    
    render(
      <Select
        options={mockOptions}
        value="option2"
        onValueChange={mockOnChange}
      />
    )

    expect(screen.getByText('Option 2')).toBeInTheDocument()
  })

  it('should close dropdown on outside click', async () => {
    const user = userEvent.setup()
    
    render(
      <div>
        <Select
          options={mockOptions}
          onValueChange={mockOnChange}
        />
        <div data-testid="outside">Outside</div>
      </div>
    )

    const trigger = screen.getByRole('button')
    await user.click(trigger)
    expect(screen.getByText('Option 1')).toBeInTheDocument()

    // Click outside
    await user.click(screen.getByTestId('outside'))
    
    // Dropdown should be closed
    expect(screen.queryByText('Option 1')).not.toBeInTheDocument()
  })

  it('should be disabled when disabled prop is true', () => {
    render(
      <Select
        options={mockOptions}
        onValueChange={mockOnChange}
        disabled
      />
    )

    expect(screen.getByRole('button')).toBeDisabled()
  })

  it('should highlight selected option in dropdown', async () => {
    const user = userEvent.setup()
    
    const { container } = render(
      <Select
        options={mockOptions}
        value="option2"
        onValueChange={mockOnChange}
      />
    )

    const trigger = screen.getByRole('button')
    await user.click(trigger)

    // Find the dropdown option with the selected styling
    const options = container.querySelectorAll('[class*="bg-orange-500/20"]')
    expect(options.length).toBeGreaterThan(0)
    expect(options[0].textContent).toBe('Option 2')
  })

  it('should apply custom className', () => {
    render(
      <Select
        options={mockOptions}
        onValueChange={mockOnChange}
        className="custom-class"
      />
    )

    expect(screen.getByRole('button').parentElement).toHaveClass('custom-class')
  })
})
