import { renderHook } from '@/__tests__/utils/test-helpers'
import { useAuth } from './use-auth'
import { AuthContext } from '@/components/auth/auth-provider'
import React from 'react'

describe('useAuth Hook', () => {
  it('should throw error when used outside AuthProvider', () => {
    // Suppress console.error for this test
    const consoleErrorSpy = jest
      .spyOn(console, 'error')
      .mockImplementation(() => {})

    expect(() => {
      renderHook(() => useAuth())
    }).toThrow('useAuth must be used within an AuthProvider')

    consoleErrorSpy.mockRestore()
  })

  it('should return auth context when used within AuthProvider', () => {
    const mockAuthContext = {
      user: { id: 1, name: 'Test User', email: 'test@example.com', created_at: '', updated_at: '' },
      token: 'test-token',
      isAuthenticated: true,
      isLoading: false,
      login: jest.fn(),
      register: jest.fn(),
      logout: jest.fn(),
    }

    const wrapper = ({ children }: { children: React.ReactNode }) => {
      return React.createElement(
        AuthContext.Provider,
        { value: mockAuthContext },
        children
      )
    }

    const { result } = renderHook(() => useAuth(), { wrapper })

    expect(result.current).toEqual(mockAuthContext)
  })

  it('should have user property when authenticated', () => {
    const mockUser = {
      id: 1,
      name: 'Test User',
      email: 'test@example.com',
      created_at: '2024-01-01',
      updated_at: '2024-01-01',
    }

    const mockAuthContext = {
      user: mockUser,
      token: 'test-token',
      isAuthenticated: true,
      isLoading: false,
      login: jest.fn(),
      register: jest.fn(),
      logout: jest.fn(),
    }

    const wrapper = ({ children }: { children: React.ReactNode }) => {
      return React.createElement(
        AuthContext.Provider,
        { value: mockAuthContext },
        children
      )
    }

    const { result } = renderHook(() => useAuth(), { wrapper })

    expect(result.current.user).toBe(mockUser)
    expect(result.current.user?.email).toBe('test@example.com')
  })

  it('should have null user when not authenticated', () => {
    const mockAuthContext = {
      user: null,
      token: null,
      isAuthenticated: false,
      isLoading: false,
      login: jest.fn(),
      register: jest.fn(),
      logout: jest.fn(),
    }

    const wrapper = ({ children }: { children: React.ReactNode }) => {
      return React.createElement(
        AuthContext.Provider,
        { value: mockAuthContext },
        children
      )
    }

    const { result } = renderHook(() => useAuth(), { wrapper })

    expect(result.current.user).toBeNull()
    expect(result.current.isAuthenticated).toBe(false)
  })

  it('should provide login function', () => {
    const mockLogin = jest.fn()
    const mockAuthContext = {
      user: null,
      token: null,
      isAuthenticated: false,
      isLoading: false,
      login: mockLogin,
      register: jest.fn(),
      logout: jest.fn(),
    }

    const wrapper = ({ children }: { children: React.ReactNode }) => {
      return React.createElement(
        AuthContext.Provider,
        { value: mockAuthContext },
        children
      )
    }

    const { result } = renderHook(() => useAuth(), { wrapper })

    expect(result.current.login).toBe(mockLogin)
  })

  it('should provide register function', () => {
    const mockRegister = jest.fn()
    const mockAuthContext = {
      user: null,
      token: null,
      isAuthenticated: false,
      isLoading: false,
      login: jest.fn(),
      register: mockRegister,
      logout: jest.fn(),
    }

    const wrapper = ({ children }: { children: React.ReactNode }) => {
      return React.createElement(
        AuthContext.Provider,
        { value: mockAuthContext },
        children
      )
    }

    const { result } = renderHook(() => useAuth(), { wrapper })

    expect(result.current.register).toBe(mockRegister)
  })

  it('should provide logout function', () => {
    const mockLogout = jest.fn()
    const mockAuthContext = {
      user: { id: 1, name: 'Test', email: 'test@example.com', created_at: '', updated_at: '' },
      token: 'test-token',
      isAuthenticated: true,
      isLoading: false,
      login: jest.fn(),
      register: jest.fn(),
      logout: mockLogout,
    }

    const wrapper = ({ children }: { children: React.ReactNode }) => {
      return React.createElement(
        AuthContext.Provider,
        { value: mockAuthContext },
        children
      )
    }

    const { result } = renderHook(() => useAuth(), { wrapper })

    expect(result.current.logout).toBe(mockLogout)
  })

  it('should report loading state during initialization', () => {
    const mockAuthContext = {
      user: null,
      token: null,
      isAuthenticated: false,
      isLoading: true,
      login: jest.fn(),
      register: jest.fn(),
      logout: jest.fn(),
    }

    const wrapper = ({ children }: { children: React.ReactNode }) => {
      return React.createElement(
        AuthContext.Provider,
        { value: mockAuthContext },
        children
      )
    }

    const { result } = renderHook(() => useAuth(), { wrapper })

    expect(result.current.isLoading).toBe(true)
  })

  it('should report loading complete', () => {
    const mockAuthContext = {
      user: null,
      token: null,
      isAuthenticated: false,
      isLoading: false,
      login: jest.fn(),
      register: jest.fn(),
      logout: jest.fn(),
    }

    const wrapper = ({ children }: { children: React.ReactNode }) => {
      return React.createElement(
        AuthContext.Provider,
        { value: mockAuthContext },
        children
      )
    }

    const { result } = renderHook(() => useAuth(), { wrapper })

    expect(result.current.isLoading).toBe(false)
  })

  it('should have token property when authenticated', () => {
    const testToken = 'jwt-token-xyz'
    const mockAuthContext = {
      user: { id: 1, name: 'Test', email: 'test@example.com', created_at: '', updated_at: '' },
      token: testToken,
      isAuthenticated: true,
      isLoading: false,
      login: jest.fn(),
      register: jest.fn(),
      logout: jest.fn(),
    }

    const wrapper = ({ children }: { children: React.ReactNode }) => {
      return React.createElement(
        AuthContext.Provider,
        { value: mockAuthContext },
        children
      )
    }

    const { result } = renderHook(() => useAuth(), { wrapper })

    expect(result.current.token).toBe(testToken)
  })
})
