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

import Login from './Login'
import { api } from './api'

vi.mock('./api', () => ({
  api: vi.fn(),
}))

describe('Login', () => {
  it('submits credentials and calls onLogin', async () => {
    const apiMock = vi.mocked(api)
    apiMock.mockResolvedValue({ ok: true })
    const onLogin = vi.fn()

    render(<Login onLogin={onLogin} />)

    fireEvent.change(screen.getByPlaceholderText('username'), { target: { value: 'brad' } })
    fireEvent.change(screen.getByPlaceholderText('password'), { target: { value: 'pass' } })
    fireEvent.click(screen.getByRole('button', { name: 'Login' }))

    await waitFor(() => {
      expect(onLogin).toHaveBeenCalledTimes(1)
    })

    expect(apiMock).toHaveBeenCalledWith('/api/login', {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify({ username: 'brad', password: 'pass' }),
    })
  })

  it('shows server error when login fails', async () => {
    const apiMock = vi.mocked(api)
    apiMock.mockRejectedValue(new Error('invalid credentials'))

    render(<Login onLogin={() => {}} />)

    fireEvent.change(screen.getByPlaceholderText('username'), { target: { value: 'brad' } })
    fireEvent.change(screen.getByPlaceholderText('password'), { target: { value: 'bad' } })
    fireEvent.click(screen.getByRole('button', { name: 'Login' }))

    expect(await screen.findByText('invalid credentials')).toBeInTheDocument()
  })
})
