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

const OPTIONS = [
  { value: 'claude', label: 'claude' },
  { value: 'codex', label: 'codex', disabled: true },
  { value: 'gpt', label: 'gpt' },
]

async function chooseOption(name: string, value: string) {
  fireEvent.click(screen.getByRole('combobox', { name }))
  fireEvent.click(await screen.findByRole('option', { name: value }))
}

describe('Select', () => {
  it('labels the control and reports the chosen value', async () => {
    const onValueChange = vi.fn()
    render(<Select label="CLI" value="claude" options={OPTIONS} onValueChange={onValueChange} />)

    await chooseOption('CLI', 'gpt')
    expect(onValueChange).toHaveBeenCalledWith('gpt')
  })

  it('keeps unavailable options visible but unselectable', async () => {
    const onValueChange = vi.fn()
    render(<Select label="CLI" value="claude" options={OPTIONS} onValueChange={onValueChange} />)
    fireEvent.click(screen.getByRole('combobox', { name: 'CLI' }))
    const option = await screen.findByRole('option', { name: 'codex' })
    expect(option).toHaveAttribute('aria-disabled', 'true')

    fireEvent.click(option)
    expect(onValueChange).not.toHaveBeenCalled()
  })

  it('shows the placeholder while no value is chosen', () => {
    render(<Select label="CLI" value="" options={OPTIONS} onValueChange={vi.fn()} placeholder="Select a CLI" />)
    expect(screen.getByRole('combobox', { name: 'CLI' })).toHaveTextContent('Select a CLI')
  })

  it('links its error text and marks the field invalid', () => {
    render(<Select label="CLI" value="" options={OPTIONS} onValueChange={vi.fn()} error="Choose a CLI." />)
    const control = screen.getByRole('combobox', { name: 'CLI' })
    expect(control).toHaveAttribute('aria-invalid', 'true')
    const describedId = control.getAttribute('aria-describedby')
    expect(document.getElementById(describedId!)?.textContent).toBe('Choose a CLI.')
  })
})