import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { MemoryRouter } from 'react-router-dom'
import { describe, expect, it, vi } from 'vitest'
import { AuthCodeForm } from '../ui/AuthCodeForm'

vi.mock('@/shared/api/client', () => ({ apiClient: { post: vi.fn() } }))
vi.mock('@/shared/model/auth', () => ({ tokenSet: vi.fn() }))

function renderForm() {
  const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } })
  const onSuccess = vi.fn()
  return render(
    <QueryClientProvider client={qc}>
      <MemoryRouter>
        <AuthCodeForm onSuccess={onSuccess} />
      </MemoryRouter>
    </QueryClientProvider>,
  )
}

describe('AuthCodeForm', () => {
  it('renders email field, code field, and buttons', () => {
    renderForm()
    expect(screen.getByLabelText(/Email/i)).toBeTruthy()
    expect(screen.getByLabelText(/Код/i)).toBeTruthy()
    expect(screen.getByRole('button', { name: 'Отправить код' })).toBeTruthy()
    expect(screen.getByRole('button', { name: 'Войти' })).toBeTruthy()
  })

  it('disables send button when email is empty', () => {
    renderForm()
    expect(screen.getByRole('button', { name: 'Отправить код' })).toBeDisabled()
  })

  it('disables login button when code.length !== 6', () => {
    renderForm()
    fireEvent.change(screen.getByLabelText(/Email/i), { target: { value: 'test@test.com' } })
    fireEvent.change(screen.getByLabelText(/Код/i), { target: { value: '123' } })
    expect(screen.getByRole('button', { name: 'Войти' })).toBeDisabled()
  })

  it('enables login button when code is 6 digits', async () => {
    renderForm()
    fireEvent.change(screen.getByLabelText(/Email/i), { target: { value: 'test@test.com' } })
    fireEvent.change(screen.getByLabelText(/Код/i), { target: { value: '123456' } })
    await waitFor(() => {
      expect(screen.getByRole('button', { name: 'Войти' })).not.toBeDisabled()
    })
  })

  it('calls onSuccess after successful verify', async () => {
    const { apiClient } = await import('@/shared/api/client')
    const { tokenSet } = await import('@/shared/model/auth')
    vi.mocked(apiClient.post).mockResolvedValue({ data: { token: 'test-token' } } as never)
    renderForm()

    fireEvent.change(screen.getByLabelText(/Email/i), { target: { value: 'test@test.com' } })
    fireEvent.change(screen.getByLabelText(/Код/i), { target: { value: '123456' } })
    fireEvent.click(screen.getByRole('button', { name: 'Войти' }))

    expect(screen.getByRole('button', { name: 'Войти' })).not.toBeDisabled()
    await waitFor(() => {
      expect(tokenSet).toHaveBeenCalledWith('test-token')
    })
  })
})
