import { describe, it, expect, vi, beforeEach } from 'vitest'
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { MemoryRouter } from 'react-router-dom'
import Register from '../pages/Register'
import { useAuthStore } from '../store/auth'

vi.mock('../store/auth', () => ({
  useAuthStore: vi.fn(),
}))

const mockNavigate = vi.fn()
vi.mock('react-router-dom', async (importOriginal) => {
  const actual = await importOriginal()
  return {
    ...actual,
    useNavigate: () => mockNavigate,
  }
})

describe('Register page', () => {
  const mockRegister = vi.fn()

  beforeEach(() => {
    vi.clearAllMocks()
    useAuthStore.mockImplementation((selector) =>
      selector({ register: mockRegister })
    )
  })

  const renderRegister = () => render(<MemoryRouter><Register /></MemoryRouter>)

  it('renders register form', () => {
    renderRegister()
    expect(screen.getByText('Создай аккаунт')).toBeInTheDocument()
    expect(screen.getByPlaceholderText('Имя')).toBeInTheDocument()
    expect(screen.getByPlaceholderText('your@email.com')).toBeInTheDocument()
    expect(screen.getByText('Создать аккаунт')).toBeInTheDocument()
  })

  it('renders login link', () => {
    renderRegister()
    expect(screen.getByText('Войти')).toBeInTheDocument()
  })

  it('submits registration successfully', async () => {
    mockRegister.mockResolvedValueOnce({})
    renderRegister()

    fireEvent.change(screen.getByPlaceholderText('Имя'), {
      target: { value: 'TestUser' },
    })
    fireEvent.change(screen.getByPlaceholderText('your@email.com'), {
      target: { value: 'test@test.com' },
    })
    fireEvent.change(screen.getByPlaceholderText('Минимум 8 символов'), {
      target: { value: 'password123' },
    })
    fireEvent.click(screen.getByText('Создать аккаунт'))

    await waitFor(() => {
      expect(mockRegister).toHaveBeenCalledWith('test@test.com', 'TestUser', 'password123')
      expect(mockNavigate).toHaveBeenCalledWith('/')
    })
  })

  it('shows error on registration failure', async () => {
    mockRegister.mockRejectedValueOnce({ response: { data: { error: 'Email already used' } } })
    renderRegister()

    fireEvent.change(screen.getByPlaceholderText('Имя'), { target: { value: 'TestUser' } })
    fireEvent.change(screen.getByPlaceholderText('your@email.com'), { target: { value: 'test@test.com' } })
    fireEvent.change(screen.getByPlaceholderText('Минимум 8 символов'), { target: { value: 'password123' } })
    fireEvent.click(screen.getByText('Создать аккаунт'))

    await waitFor(() => {
      expect(screen.getByText('Email already used')).toBeInTheDocument()
    })
  })

  it('shows default error on failure', async () => {
    mockRegister.mockRejectedValueOnce(new Error('Error'))
    renderRegister()

    fireEvent.change(screen.getByPlaceholderText('Имя'), { target: { value: 'User' } })
    fireEvent.change(screen.getByPlaceholderText('your@email.com'), { target: { value: 'a@b.com' } })
    fireEvent.change(screen.getByPlaceholderText('Минимум 8 символов'), { target: { value: 'password1' } })
    fireEvent.click(screen.getByText('Создать аккаунт'))

    await waitFor(() => {
      expect(screen.getByText('Ошибка регистрации')).toBeInTheDocument()
    })
  })

  it('toggles password visibility', () => {
    renderRegister()
    const passwordInput = screen.getByPlaceholderText('Минимум 8 символов')
    expect(passwordInput.type).toBe('password')

    const toggleBtn = passwordInput.parentElement.querySelector('button[type="button"]')
    fireEvent.click(toggleBtn)
    expect(passwordInput.type).toBe('text')
  })
})
