import React from 'react'
import { renderWithProviders, userEvent, waitFor } from '@/__tests__/utils/test-helpers'
import { useAuth } from '@/hooks/use-auth'
import RegisterPage from './page'

jest.mock('@/hooks/use-auth')
jest.mock('@/components/ui/button', () => ({
  Button: ({ children, ...props }: any) => <button {...props}>{children}</button>,
}))
jest.mock('@/components/ui/input', () => ({
  Input: (props: any) => <input {...props} />,
}))
jest.mock('@/components/ui/label', () => ({
  Label: ({ children, ...props }: any) => <label {...props}>{children}</label>,
}))
jest.mock('@/components/ui/card', () => ({
  Card: ({ children }: any) => <div data-testid="card">{children}</div>,
  CardHeader: ({ children }: any) => <div data-testid="card-header">{children}</div>,
  CardTitle: ({ children }: any) => <h2>{children}</h2>,
  CardDescription: ({ children }: any) => <p>{children}</p>,
  CardContent: ({ children }: any) => <div data-testid="card-content">{children}</div>,
  CardFooter: ({ children }: any) => <div data-testid="card-footer">{children}</div>,
}))
jest.mock('lucide-react', () => ({
  Eye: () => <span data-testid="eye-icon" />,
  EyeOff: () => <span data-testid="eye-off-icon" />,
}))
jest.mock('next/link', () => ({
  __esModule: true,
  default: ({ children, href }: any) => <a href={href}>{children}</a>,
}))

describe('RegisterPage', () => {
  const mockRegister = jest.fn()

  beforeEach(() => {
    jest.clearAllMocks()
    ;(useAuth as jest.Mock).mockReturnValue({
      register: mockRegister,
    })
  })

  it('should render registration form', () => {
    const { getByText, getByPlaceholderText } = renderWithProviders(<RegisterPage />)

    expect(getByText('Create an account')).toBeInTheDocument()
    expect(getByText('Get started with your portfolio hosting')).toBeInTheDocument()
    expect(getByPlaceholderText('John Doe')).toBeInTheDocument()
    expect(getByPlaceholderText('you@example.com')).toBeInTheDocument()
  })

  it('should display required field errors', async () => {
    const { getByRole, getByText } = renderWithProviders(<RegisterPage />)

    const submitButton = getByRole('button', { name: /create account/i })
    await userEvent.click(submitButton)

    expect(getByText('Name is required')).toBeInTheDocument()
    expect(getByText('Email is required')).toBeInTheDocument()
    expect(getByText('Password is required')).toBeInTheDocument()
    expect(getByText('Please confirm your password')).toBeInTheDocument()
  })

  it('should validate email format', async () => {
    const { getByPlaceholderText, getByRole, getByText } = renderWithProviders(<RegisterPage />)

    const nameInput = getByPlaceholderText('John Doe') as HTMLInputElement
    const emailInput = getByPlaceholderText('you@example.com') as HTMLInputElement
    const submitButton = getByRole('button', { name: /create account/i })

    await userEvent.type(nameInput, 'John Doe')
    await userEvent.type(emailInput, 'invalid-email')
    await userEvent.click(submitButton)

    expect(getByText('Invalid email address')).toBeInTheDocument()
  })

  it('should validate password minimum length', async () => {
    const inputs = document.querySelectorAll('input')
    const { getByPlaceholderText, getByRole, getByText } = renderWithProviders(<RegisterPage />)

    const nameInput = getByPlaceholderText('John Doe') as HTMLInputElement
    const emailInput = getByPlaceholderText('you@example.com') as HTMLInputElement
    const submitButton = getByRole('button', { name: /create account/i })

    await userEvent.type(nameInput, 'John Doe')
    await userEvent.type(emailInput, 'test@example.com')
    await userEvent.type(inputs[2], '12345') // Password field
    await userEvent.click(submitButton)

    expect(getByText('Password must be at least 6 characters')).toBeInTheDocument()
  })

  it('should validate password confirmation match', async () => {
    const inputs = document.querySelectorAll('input')
    const { getByPlaceholderText, getByRole, getByText } = renderWithProviders(<RegisterPage />)

    const nameInput = getByPlaceholderText('John Doe') as HTMLInputElement
    const emailInput = getByPlaceholderText('you@example.com') as HTMLInputElement
    const submitButton = getByRole('button', { name: /create account/i })

    await userEvent.type(nameInput, 'John Doe')
    await userEvent.type(emailInput, 'test@example.com')
    await userEvent.type(inputs[2], 'password123') // Password
    await userEvent.type(inputs[3], 'password456') // Confirm password - different
    await userEvent.click(submitButton)

    expect(getByText('Passwords do not match')).toBeInTheDocument()
  })

  it('should submit form with valid data', async () => {
    mockRegister.mockResolvedValueOnce(undefined)

    const inputs = document.querySelectorAll('input')
    const { getByPlaceholderText, getByRole } = renderWithProviders(<RegisterPage />)

    const nameInput = getByPlaceholderText('John Doe') as HTMLInputElement
    const emailInput = getByPlaceholderText('you@example.com') as HTMLInputElement
    const submitButton = getByRole('button', { name: /create account/i })

    await userEvent.type(nameInput, 'John Doe')
    await userEvent.type(emailInput, 'john@example.com')
    await userEvent.type(inputs[2], 'password123')
    await userEvent.type(inputs[3], 'password123')
    await userEvent.click(submitButton)

    expect(mockRegister).toHaveBeenCalledWith({
      name: 'John Doe',
      email: 'john@example.com',
      password: 'password123',
      password_confirmation: 'password123',
    })
  })

  it('should display error message on registration failure', async () => {
    const errorMessage = 'Email already exists'
    mockRegister.mockRejectedValueOnce(new Error(errorMessage))

    const inputs = document.querySelectorAll('input')
    const { getByPlaceholderText, getByRole, getByText } = renderWithProviders(<RegisterPage />)

    const nameInput = getByPlaceholderText('John Doe') as HTMLInputElement
    const emailInput = getByPlaceholderText('you@example.com') as HTMLInputElement
    const submitButton = getByRole('button', { name: /create account/i })

    await userEvent.type(nameInput, 'John Doe')
    await userEvent.type(emailInput, 'existing@example.com')
    await userEvent.type(inputs[2], 'password123')
    await userEvent.type(inputs[3], 'password123')
    await userEvent.click(submitButton)

    await waitFor(() => {
      expect(getByText(errorMessage)).toBeInTheDocument()
    })
  })

  it('should toggle password visibility', async () => {
    const inputs = document.querySelectorAll('input')
    renderWithProviders(<RegisterPage />)

    const passwordInput = inputs[2] as HTMLInputElement
    const toggleButton = passwordInput.parentElement?.querySelector('button')

    expect(passwordInput.type).toBe('password')

    if (toggleButton) {
      await userEvent.click(toggleButton)
      expect(passwordInput.type).toBe('text')

      await userEvent.click(toggleButton)
      expect(passwordInput.type).toBe('password')
    }
  })

  it('should toggle confirm password visibility', async () => {
    const inputs = document.querySelectorAll('input')
    renderWithProviders(<RegisterPage />)

    const confirmPasswordInput = inputs[3] as HTMLInputElement
    const toggleButtons = document.querySelectorAll('button')
    const confirmToggleButton = toggleButtons[toggleButtons.length - 1]

    expect(confirmPasswordInput.type).toBe('password')

    await userEvent.click(confirmToggleButton)
    expect(confirmPasswordInput.type).toBe('text')

    await userEvent.click(confirmToggleButton)
    expect(confirmPasswordInput.type).toBe('password')
  })

  it('should show loading state during submission', async () => {
    mockRegister.mockImplementationOnce(
      () =>
        new Promise((resolve) => {
          setTimeout(resolve, 100)
        })
    )

    const inputs = document.querySelectorAll('input')
    const { getByPlaceholderText, getByRole, getByText } = renderWithProviders(<RegisterPage />)

    const nameInput = getByPlaceholderText('John Doe') as HTMLInputElement
    const emailInput = getByPlaceholderText('you@example.com') as HTMLInputElement
    const submitButton = getByRole('button', { name: /create account/i }) as HTMLButtonElement

    await userEvent.type(nameInput, 'John Doe')
    await userEvent.type(emailInput, 'test@example.com')
    await userEvent.type(inputs[2], 'password123')
    await userEvent.type(inputs[3], 'password123')
    await userEvent.click(submitButton)

    expect(submitButton.disabled).toBe(true)
    expect(getByText('Creating account...')).toBeInTheDocument()
  })

  it('should have link to login page', () => {
    const { getByRole } = renderWithProviders(<RegisterPage />)

    const loginLink = getByRole('link', { name: /sign in/i })
    expect(loginLink).toHaveAttribute('href', '/login')
  })

  it('should validate all fields before submission', async () => {
    const { getByRole } = renderWithProviders(<RegisterPage />)

    const submitButton = getByRole('button', { name: /create account/i })
    await userEvent.click(submitButton)

    expect(mockRegister).not.toHaveBeenCalled()
  })

  it('should handle real-time validation updates', async () => {
    const inputs = document.querySelectorAll('input')
    const { getByPlaceholderText, getByRole, queryByText } = renderWithProviders(<RegisterPage />)

    const nameInput = getByPlaceholderText('John Doe') as HTMLInputElement
    const submitButton = getByRole('button', { name: /create account/i })

    // Try to submit without name
    await userEvent.click(submitButton)
    expect(queryByText('Name is required')).toBeInTheDocument()

    // Add name
    await userEvent.type(nameInput, 'John Doe')

    // Trigger re-validation
    await userEvent.click(submitButton)
    expect(queryByText('Email is required')).toBeInTheDocument()
  })
})
