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

const GREEN_SCREEN = '\u001b[32mready\u001b[0m\n$ '

describe('TerminalView', () => {
  it('renders the captured screen', () => {
    render(<TerminalView screen={GREEN_SCREEN} state="attached" label="session s1" />)
    expect(screen.getByTestId('terminal-output')).toHaveTextContent('ready')
  })

  it('shows the reason instead of an empty pane when unavailable', () => {
    render(<TerminalView screen={null} state="unavailable" reason="tmux is not installed on this host" label="session s1" />)
    expect(screen.getByTestId('terminal-output')).toHaveTextContent('tmux is not installed on this host')
  })

  it('says it is connecting before the first capture', () => {
    render(<TerminalView screen={null} state="connecting" label="session s1" />)
    expect(screen.getByTestId('terminal-output')).toHaveTextContent('Connecting to the session')
  })

  it('sends typed text followed by Enter', () => {
    const onSend = vi.fn()
    render(<TerminalView screen={GREEN_SCREEN} state="attached" label="session s1" onSend={onSend} />)
    const input = screen.getByLabelText('Send input to session s1')
    fireEvent.change(input, { target: { value: 'continue' } })
    fireEvent.click(screen.getByRole('button', { name: 'Send' }))
    expect(onSend).toHaveBeenNthCalledWith(1, { text: 'continue' })
    expect(onSend).toHaveBeenNthCalledWith(2, { key: 'Enter' })
  })

  it('sends Enter alone when the composer is empty', () => {
    const onSend = vi.fn()
    render(<TerminalView screen={GREEN_SCREEN} state="attached" label="session s1" onSend={onSend} />)
    fireEvent.keyDown(screen.getByLabelText('Send input to session s1'), { key: 'Enter' })
    expect(onSend).toHaveBeenCalledTimes(1)
    expect(onSend).toHaveBeenCalledWith({ key: 'Enter' })
  })

  it('sends a control key from its button', () => {
    const onSend = vi.fn()
    render(<TerminalView screen={GREEN_SCREEN} state="attached" label="session s1" onSend={onSend} />)
    fireEvent.click(screen.getByRole('button', { name: 'Send C-c' }))
    expect(onSend).toHaveBeenCalledWith({ key: 'C-c' })
  })

  it('disables input when the session is not attached', () => {
    render(<TerminalView screen={GREEN_SCREEN} state="ended" reason="Session ended." label="session s1" onSend={vi.fn()} />)
    expect(screen.getByLabelText('Send input to session s1')).toBeDisabled()
    expect(screen.getByRole('button', { name: 'Send' })).toBeDisabled()
  })

  it('disables input while a send is in flight', () => {
    render(<TerminalView screen={GREEN_SCREEN} state="attached" label="session s1" onSend={vi.fn()} busy />)
    expect(screen.getByRole('button', { name: 'Send' })).toBeDisabled()
  })

  it('omits the capture note when there is nothing to report', () => {
    const { rerender } = render(<TerminalView screen={GREEN_SCREEN} state="attached" label="session s1" />)
    expect(screen.queryByText(/captured/i)).toBeNull()
    rerender(<TerminalView screen={GREEN_SCREEN} state="attached" label="session s1" capturedNote="captured 2s ago" />)
    expect(screen.getByText('captured 2s ago')).toBeInTheDocument()
  })
})
