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

import { Input } from '../Input'

/**
 * The input's accessibility wiring, which is load-bearing rather than cosmetic:
 * a form that asks for a domain price and announces its errors only visually is
 * a form some people cannot correct.
 */
describe('Input', () => {
  it('associates its label with the control', () => {
    render(<Input label="Asking price" />)

    // getByLabelText only resolves if the label is genuinely associated.
    expect(screen.getByLabelText('Asking price')).toBeDefined()
  })

  it('keeps a hidden label available to assistive technology', () => {
    render(<Input label="Search domains" labelHidden />)

    expect(screen.getByLabelText('Search domains')).toBeDefined()
  })

  it('marks the field invalid and announces the error', () => {
    render(<Input label="Email address" error="That address is taken." />)

    const field = screen.getByLabelText('Email address')
    expect(field.getAttribute('aria-invalid')).toBe('true')

    const alert = screen.getByRole('alert')
    expect(alert.textContent).toBe('That address is taken.')
    // The error must be the field's description, not merely nearby text.
    expect(field.getAttribute('aria-describedby')).toContain(alert.id)
  })

  it('describes the field with its hint when there is no error', () => {
    render(<Input label="Phone number" hint="Used for account recovery." />)

    const field = screen.getByLabelText('Phone number')
    const described = field.getAttribute('aria-describedby')

    expect(described).toBeTruthy()
    expect(screen.getByText('Used for account recovery.').id).toBe(described)
    expect(field.getAttribute('aria-invalid')).toBeNull()
  })

  it('replaces the hint with the error rather than showing both', () => {
    render(<Input label="Phone number" hint="Optional." error="That number is in use." />)

    expect(screen.queryByText('Optional.')).toBeNull()
    expect(screen.getByRole('alert')).toBeDefined()
  })

  it('uses the control border at rest, which meets the contrast requirement', () => {
    render(<Input label="Asking price" />)

    // The resting border is a control boundary; a hairline fails WCAG 1.4.11.
    expect(screen.getByLabelText('Asking price').className).toContain('border-border-control')
  })

  it('marks a required field for both sighted and assistive users', () => {
    render(<Input label="Full name" required />)

    const field = screen.getByLabelText(/Full name/)
    expect(field.hasAttribute('required')).toBe(true)
  })
})
