import { describe, it, expect, vi, beforeEach } from 'vitest'
import { render, screen, waitFor } from '../../../test/utils'
import { RequireAuth } from '../RequireAuth'
import { useAuthStore } from '../../../lib/auth'


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

const mockUseAuthStore = vi.mocked(useAuthStore)

describe('RequireAuth', () => {
  beforeEach(() => {
    vi.clearAllMocks()
  })

  it('renders children when user is authenticated', () => {
    mockUseAuthStore.mockReturnValue({
      isAuthenticated: true,
      isLoading: false,
      refreshAuth: vi.fn()
    })

    render(
      <RequireAuth>
        <div>Protected content</div>
      </RequireAuth>
    )

    expect(screen.getByText('Protected content')).toBeInTheDocument()
  })

  it('shows loading spinner when loading', () => {
    mockUseAuthStore.mockReturnValue({
      isAuthenticated: false,
      isLoading: true,
      refreshAuth: vi.fn()
    })

    render(
      <RequireAuth>
        <div>Protected content</div>
      </RequireAuth>
    )

    expect(screen.getByText((content, element) => 
      element?.classList.contains('animate-spin') || false
    )).toBeInTheDocument() // Loading spinner
    expect(screen.queryByText('Protected content')).not.toBeInTheDocument()
  })

  it('attempts to refresh auth when not authenticated', async () => {
    const mockRefreshAuth = vi.fn().mockResolvedValue(undefined)
    
    mockUseAuthStore.mockReturnValue({
      isAuthenticated: false,
      isLoading: false,
      refreshAuth: mockRefreshAuth
    })

    render(
      <RequireAuth>
        <div>Protected content</div>
      </RequireAuth>
    )

    await waitFor(() => {
      expect(mockRefreshAuth).toHaveBeenCalled()
    })
  })

  it('handles refresh auth failure gracefully', async () => {
    const mockRefreshAuth = vi.fn().mockRejectedValue(new Error('Refresh failed'))
    
    mockUseAuthStore.mockReturnValue({
      isAuthenticated: false,
      isLoading: false,
      refreshAuth: mockRefreshAuth
    })

    render(
      <RequireAuth>
        <div>Protected content</div>
      </RequireAuth>
    )

    await waitFor(() => {
      expect(mockRefreshAuth).toHaveBeenCalled()
    })

    // Should not crash on refresh failure
    expect(screen.queryByText('Protected content')).not.toBeInTheDocument()
  })

  it('does not call refreshAuth multiple times when already loading', () => {
    const mockRefreshAuth = vi.fn().mockResolvedValue(undefined)
    
    mockUseAuthStore.mockReturnValue({
      isAuthenticated: false,
      isLoading: true,
      refreshAuth: mockRefreshAuth
    })

    render(
      <RequireAuth>
        <div>Protected content</div>
      </RequireAuth>
    )

    expect(mockRefreshAuth).not.toHaveBeenCalled()
  })

  it('does not call refreshAuth when already authenticated', () => {
    const mockRefreshAuth = vi.fn()
    
    mockUseAuthStore.mockReturnValue({
      isAuthenticated: true,
      isLoading: false,
      refreshAuth: mockRefreshAuth
    })

    render(
      <RequireAuth>
        <div>Protected content</div>
      </RequireAuth>
    )

    expect(mockRefreshAuth).not.toHaveBeenCalled()
  })
})