import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { BrowserRouter } from 'react-router-dom'
import Login from './Login'

let mockLogin = vi.fn().mockResolvedValue({ id: '1', name: 'John', email: 'john@example.com' })

vi.mock('../context/AuthContext', () => ({
  AuthProvider: ({ children }) => children,
  useAuth: () => ({ 
    login: mockLogin,
    user: null, 
    loading: false, 
    logout: vi.fn() 
  })
}))

vi.mock('../context/SocketContext', () => ({
  SocketProvider: ({ children }) => children,
  useSocket: () => ({ unreadCount: 0, notifications: [], joinBooking: vi.fn(), sendMessage: vi.fn(), markRead: vi.fn(), markAllRead: vi.fn() })
}))

vi.mock('react-hot-toast', () => ({
  default: { success: vi.fn(), error: vi.fn() },
  toast: { success: vi.fn(), error: vi.fn() }
}))

const renderWithRouter = () => {
  return render(
    <BrowserRouter>
      <Login />
    </BrowserRouter>
  )
}

describe('Login Page', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    mockLogin.mockResolvedValue({ id: '1', name: 'John', email: 'john@example.com' })
  })

  it('renders login form with email and password fields', () => {
    renderWithRouter()
    expect(screen.getByPlaceholderText('you@example.com')).toBeInTheDocument()
    expect(screen.getByPlaceholderText('••••••••')).toBeInTheDocument()
    expect(screen.getByText('Sign In')).toBeInTheDocument()
  })

  it('shows Handyman branding', () => {
    renderWithRouter()
    expect(screen.getAllByText('Handyman').length).toBeGreaterThan(0)
    expect(screen.getByText('Welcome back')).toBeInTheDocument()
  })

  it('shows remember me and forgot password links', () => {
    renderWithRouter()
    expect(screen.getByText('Remember me')).toBeInTheDocument()
    expect(screen.getByText('Forgot password?')).toBeInTheDocument()
  })

  it('shows social login buttons', () => {
    renderWithRouter()
    expect(screen.getByText('Google')).toBeInTheDocument()
    expect(screen.getByText('GitHub')).toBeInTheDocument()
  })

  it('shows sign up link', () => {
    renderWithRouter()
    expect(screen.getByText('Sign up')).toBeInTheDocument()
  })

  it('updates form fields on input', () => {
    renderWithRouter()
    const emailInput = screen.getByPlaceholderText('you@example.com')
    const passwordInput = screen.getByPlaceholderText('••••••••')
    
    fireEvent.change(emailInput, { target: { value: 'test@example.com' } })
    fireEvent.change(passwordInput, { target: { value: 'password123' } })
    
    expect(emailInput).toHaveValue('test@example.com')
    expect(passwordInput).toHaveValue('password123')
  })

  it('toggles password visibility', () => {
    renderWithRouter()
    const passwordInput = screen.getByPlaceholderText('••••••••')
    expect(passwordInput).toHaveAttribute('type', 'password')
    
    const toggleButton = passwordInput.parentElement?.querySelector('button')
    fireEvent.click(toggleButton)
    expect(passwordInput).toHaveAttribute('type', 'text')
    
    fireEvent.click(toggleButton)
    expect(passwordInput).toHaveAttribute('type', 'password')
  })

  it('calls login on form submit', async () => {
    renderWithRouter()
    
    const emailInput = screen.getByPlaceholderText('you@example.com')
    const passwordInput = screen.getByPlaceholderText('••••••••')
    const submitButton = screen.getByText('Sign In')
    
    fireEvent.change(emailInput, { target: { value: 'test@example.com' } })
    fireEvent.change(passwordInput, { target: { value: 'password123' } })
    fireEvent.click(submitButton)
    
    await waitFor(() => {
      expect(mockLogin).toHaveBeenCalledWith('test@example.com', 'password123')
    })
  })

  it('shows loading state during submit', async () => {
    mockLogin.mockImplementation(() => new Promise(resolve => setTimeout(resolve, 100)))
    
    renderWithRouter()
    const emailInput = screen.getByPlaceholderText('you@example.com')
    const passwordInput = screen.getByPlaceholderText('••••••••')
    const submitButton = screen.getByRole('button', { name: 'Sign In' })
    
    fireEvent.change(emailInput, { target: { value: 'test@example.com' } })
    fireEvent.change(passwordInput, { target: { value: 'password123' } })
    fireEvent.click(submitButton)
    
    // Verify login was called
    await waitFor(() => {
      expect(mockLogin).toHaveBeenCalled()
    })
  })
})