/**
 * @ai-summary Tests for useAdminAccess hook
 */

import { renderHook, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { useAuth0 } from '@auth0/auth0-react';
import { useAdminAccess } from '../../../core/auth/useAdminAccess';
import { adminApi } from '../api/admin.api';

jest.mock('@auth0/auth0-react');
jest.mock('../api/admin.api');

const mockUseAuth0 = useAuth0 as jest.MockedFunction<typeof useAuth0>;
const mockAdminApi = adminApi as jest.Mocked<typeof adminApi>;

const createWrapper = () => {
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: {
        retry: false,
      },
    },
  });
  return ({ children }: { children: React.ReactNode }) => (
    <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
  );
};

describe('useAdminAccess', () => {
  beforeEach(() => {
    jest.clearAllMocks();
  });

  it('should return loading state initially', () => {
    mockUseAuth0.mockReturnValue({
      isAuthenticated: true,
      isLoading: false,
    } as any);

    const { result } = renderHook(() => useAdminAccess(), {
      wrapper: createWrapper(),
    });

    expect(result.current.loading).toBe(true);
    expect(result.current.isAdmin).toBe(false);
  });

  it('should return isAdmin true when user is admin', async () => {
    mockUseAuth0.mockReturnValue({
      isAuthenticated: true,
      isLoading: false,
    } as any);

    mockAdminApi.verifyAccess.mockResolvedValue({
      isAdmin: true,
      adminRecord: {
        auth0Sub: 'auth0|123',
        email: 'admin@example.com',
        role: 'admin',
        createdAt: '2024-01-01',
        createdBy: 'system',
        revokedAt: null,
        updatedAt: '2024-01-01',
      },
    });

    const { result } = renderHook(() => useAdminAccess(), {
      wrapper: createWrapper(),
    });

    await waitFor(() => expect(result.current.loading).toBe(false));

    expect(result.current.isAdmin).toBe(true);
    expect(result.current.adminRecord).toBeTruthy();
    expect(result.current.error).toBeUndefined();
  });

  it('should return isAdmin false when user is not admin', async () => {
    mockUseAuth0.mockReturnValue({
      isAuthenticated: true,
      isLoading: false,
    } as any);

    mockAdminApi.verifyAccess.mockResolvedValue({
      isAdmin: false,
      adminRecord: null,
    });

    const { result } = renderHook(() => useAdminAccess(), {
      wrapper: createWrapper(),
    });

    await waitFor(() => expect(result.current.loading).toBe(false));

    expect(result.current.isAdmin).toBe(false);
    expect(result.current.adminRecord).toBeNull();
    expect(result.current.error).toBeUndefined();
  });

  it('should handle errors gracefully', async () => {
    mockUseAuth0.mockReturnValue({
      isAuthenticated: true,
      isLoading: false,
    } as any);

    const error = new Error('API error');
    mockAdminApi.verifyAccess.mockRejectedValue(error);

    const { result } = renderHook(() => useAdminAccess(), {
      wrapper: createWrapper(),
    });

    await waitFor(() => expect(result.current.loading).toBe(false));

    expect(result.current.isAdmin).toBe(false);
    expect(result.current.error).toBeTruthy();
  });

  it('should not query when user is not authenticated', () => {
    mockUseAuth0.mockReturnValue({
      isAuthenticated: false,
      isLoading: false,
    } as any);

    const { result } = renderHook(() => useAdminAccess(), {
      wrapper: createWrapper(),
    });

    expect(mockAdminApi.verifyAccess).not.toHaveBeenCalled();
    expect(result.current.isAdmin).toBe(false);
  });
});
