import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { StageTransitionModal } from '../StageTransitionModal'

const stages = [
  { id: 'prospect', label: 'Prospect' },
  { id: 'qualified', label: 'Qualified' },
  { id: 'proposal', label: 'Proposal' },
  { id: 'closed', label: 'Closed Won' },
]

const baseProps = {
  open: true,
  onClose: jest.fn(),
  onConfirm: jest.fn(),
  currentStage: 'prospect',
  stages,
}

describe('StageTransitionModal', () => {
  beforeEach(() => {
    jest.clearAllMocks()
  })

  it('renders nothing when open is false', () => {
    render(<StageTransitionModal {...baseProps} open={false} />)
    expect(screen.queryByText(/move/i)).not.toBeInTheDocument()
  })

  it('renders dialog when open is true', () => {
    render(<StageTransitionModal {...baseProps} />)
    expect(screen.getByText('Move Item to Stage')).toBeInTheDocument()
  })

  it('includes entityName in dialog title when provided', () => {
    render(<StageTransitionModal {...baseProps} entityName="ACME Deal" />)
    expect(screen.getByText('Move "ACME Deal" to Stage')).toBeInTheDocument()
  })

  it('shows the current stage label', () => {
    render(<StageTransitionModal {...baseProps} />)
    expect(screen.getByText('Prospect')).toBeInTheDocument()
  })

  it('excludes the current stage from the new stage dropdown', () => {
    render(<StageTransitionModal {...baseProps} />)
    const options = screen.getAllByRole('option')
    const optionValues = options.map((o) => (o as HTMLOptionElement).value)
    expect(optionValues).not.toContain('prospect')
    expect(optionValues).toContain('qualified')
    expect(optionValues).toContain('proposal')
    expect(optionValues).toContain('closed')
  })

  it('defaults to the first non-current stage', () => {
    render(<StageTransitionModal {...baseProps} />)
    const select = screen.getByLabelText('New Stage') as HTMLSelectElement
    expect(select.value).toBe('qualified')
  })

  it('calls onConfirm with selected stage when Confirm is clicked', () => {
    const onConfirm = jest.fn()
    render(<StageTransitionModal {...baseProps} onConfirm={onConfirm} />)
    fireEvent.click(screen.getByRole('button', { name: /confirm/i }))
    expect(onConfirm).toHaveBeenCalledWith('qualified', undefined)
  })

  it('passes notes to onConfirm when notes are entered', () => {
    const onConfirm = jest.fn()
    render(<StageTransitionModal {...baseProps} onConfirm={onConfirm} />)

    fireEvent.change(screen.getByLabelText(/notes/i), {
      target: { value: 'Moving due to demo completed' },
    })
    fireEvent.click(screen.getByRole('button', { name: /confirm/i }))

    expect(onConfirm).toHaveBeenCalledWith('qualified', 'Moving due to demo completed')
  })

  it('passes undefined for whitespace-only notes', () => {
    const onConfirm = jest.fn()
    render(<StageTransitionModal {...baseProps} onConfirm={onConfirm} />)

    fireEvent.change(screen.getByLabelText(/notes/i), { target: { value: '   ' } })
    fireEvent.click(screen.getByRole('button', { name: /confirm/i }))

    expect(onConfirm).toHaveBeenCalledWith('qualified', undefined)
  })

  it('calls onClose when Cancel is clicked', () => {
    const onClose = jest.fn()
    render(<StageTransitionModal {...baseProps} onClose={onClose} />)
    fireEvent.click(screen.getByRole('button', { name: /cancel/i }))
    expect(onClose).toHaveBeenCalledTimes(1)
  })

  it('calls onClose when backdrop is clicked', () => {
    const onClose = jest.fn()
    const { container } = render(
      <StageTransitionModal {...baseProps} onClose={onClose} />
    )
    const backdrop = container.querySelector('[aria-hidden="true"]')
    fireEvent.click(backdrop!)
    expect(onClose).toHaveBeenCalledTimes(1)
  })

  it('does not call onClose when backdrop clicked while submitting', () => {
    const onClose = jest.fn()
    const { container } = render(
      <StageTransitionModal {...baseProps} onClose={onClose} isSubmitting />
    )
    const backdrop = container.querySelector('[aria-hidden="true"]')
    fireEvent.click(backdrop!)
    expect(onClose).not.toHaveBeenCalled()
  })

  it('shows Moving... when isSubmitting', () => {
    render(<StageTransitionModal {...baseProps} isSubmitting />)
    expect(screen.getByText('Moving...')).toBeInTheDocument()
  })

  it('disables select and textarea when isSubmitting', () => {
    render(<StageTransitionModal {...baseProps} isSubmitting />)
    expect(screen.getByLabelText('New Stage')).toBeDisabled()
    expect(screen.getByLabelText(/notes/i)).toBeDisabled()
  })

  it('disables Cancel when isSubmitting', () => {
    render(<StageTransitionModal {...baseProps} isSubmitting />)
    expect(screen.getByRole('button', { name: /cancel/i })).toBeDisabled()
  })

  it('Confirm button is disabled while submitting', () => {
    render(<StageTransitionModal {...baseProps} isSubmitting />)
    expect(screen.getByText('Moving...').closest('button')).toBeDisabled()
  })

  it('resets notes when dialog reopens', () => {
    const { rerender } = render(
      <StageTransitionModal {...baseProps} open={false} />
    )
    rerender(<StageTransitionModal {...baseProps} open />)
    expect(screen.getByLabelText(/notes/i)).toHaveValue('')
  })

  it('allows changing the target stage via the select', () => {
    render(<StageTransitionModal {...baseProps} />)
    const select = screen.getByLabelText('New Stage') as HTMLSelectElement
    fireEvent.change(select, { target: { value: 'closed' } })
    expect(select.value).toBe('closed')
  })

  it('calls onConfirm with the newly selected stage', () => {
    const onConfirm = jest.fn()
    render(<StageTransitionModal {...baseProps} onConfirm={onConfirm} />)
    fireEvent.change(screen.getByLabelText('New Stage'), { target: { value: 'closed' } })
    fireEvent.click(screen.getByRole('button', { name: /confirm/i }))
    expect(onConfirm).toHaveBeenCalledWith('closed', undefined)
  })

  it('renders Current Stage label', () => {
    render(<StageTransitionModal {...baseProps} />)
    expect(screen.getByText('Current Stage')).toBeInTheDocument()
  })

  it('renders New Stage label', () => {
    render(<StageTransitionModal {...baseProps} />)
    expect(screen.getByText('New Stage')).toBeInTheDocument()
  })
})
