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 { AuthPasswordForm } from '../ui/AuthPasswordForm'

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

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

describe('AuthPasswordForm', () => {
  it('renders login button when isRegister=false', () => {
    renderForm(false)
    expect(screen.getByRole('button', { name: 'Войти' })).toBeTruthy()
    expect(screen.getByText('Вход')).toBeTruthy()
  })

  it('renders register button and passwordConfirm when isRegister=true', () => {
    renderForm(true)
    expect(screen.getByRole('button', { name: 'Зарегистрироваться' })).toBeTruthy()
    expect(screen.getByLabelText(/Подтверждение пароля/i)).toBeTruthy()
  })

  it('disables button when password < 8 chars', async () => {
    const { apiClient } = await import('@/shared/api/client')
    vi.mocked(apiClient.post).mockResolvedValue({} as never)
    renderForm(true)

    fireEvent.change(screen.getByLabelText(/Email/i), { target: { value: 'test@test.com' } })
    fireEvent.change(screen.getByLabelText(/Пароль/i), { target: { value: '123' } })

    await waitFor(() => {
      expect(screen.getByRole('button', { name: 'Зарегистрироваться' })).toBeDisabled()
    })
  })

  it('shows error when passwords do not match', async () => {
    renderForm(true)

    fireEvent.change(screen.getByLabelText(/Email/i), { target: { value: 'test@test.com' } })
    fireEvent.change(screen.getByLabelText(/Пароль/i), { target: { value: 'password123' } })
    fireEvent.change(screen.getByLabelText(/Подтверждение пароля/i), { target: { value: 'different' } })

    await waitFor(() => {
      expect(screen.getByText('Пароли не совпадают')).toBeTruthy()
    })
  })

  it('calls onSuccess after successful login', 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(false)

    fireEvent.change(screen.getByLabelText(/Email/i), { target: { value: 'test@test.com' } })
    fireEvent.change(screen.getByLabelText(/Пароль/i), { target: { value: 'password123' } })
    fireEvent.click(screen.getByRole('button', { name: 'Войти' }))

    await waitFor(() => {
      expect(tokenSet).toHaveBeenCalledWith('test-token')
    })
  })
})
