/**
 * @ai-summary Tests for admin user management hooks
 */

import { renderHook, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { useAuth0 } from '@auth0/auth0-react';
import { useAdmins, useCreateAdmin, useRevokeAdmin, useReinstateAdmin } from '../hooks/useAdmins';
import { adminApi } from '../api/admin.api';
import toast from 'react-hot-toast';

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

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('Admin user management hooks', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    mockUseAuth0.mockReturnValue({
      isAuthenticated: true,
      isLoading: false,
    } as any);
  });

  describe('useAdmins', () => {
    it('should fetch admin users', async () => {
      const mockAdmins = [
        {
          auth0Sub: 'auth0|123',
          email: 'admin1@example.com',
          role: 'admin',
          createdAt: '2024-01-01',
          createdBy: 'system',
          revokedAt: null,
          updatedAt: '2024-01-01',
        },
      ];

      mockAdminApi.listAdmins.mockResolvedValue(mockAdmins);

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

      await waitFor(() => expect(result.current.isSuccess).toBe(true));

      expect(result.current.data).toEqual(mockAdmins);
      expect(mockAdminApi.listAdmins).toHaveBeenCalledTimes(1);
    });
  });

  describe('useCreateAdmin', () => {
    it('should create admin and show success toast', async () => {
      const newAdmin = {
        auth0Sub: 'auth0|456',
        email: 'newadmin@example.com',
        role: 'admin',
        createdAt: '2024-01-01',
        createdBy: 'auth0|123',
        revokedAt: null,
        updatedAt: '2024-01-01',
      };

      mockAdminApi.createAdmin.mockResolvedValue(newAdmin);

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

      result.current.mutate({
        email: 'newadmin@example.com',
        role: 'admin',
      });

      await waitFor(() => expect(result.current.isSuccess).toBe(true));

      expect(mockAdminApi.createAdmin).toHaveBeenCalledWith({
        email: 'newadmin@example.com',
        role: 'admin',
      });
      expect(toast.success).toHaveBeenCalledWith('Admin added successfully');
    });

    it('should handle create admin error', async () => {
      const error = {
        response: {
          data: {
            error: 'Admin already exists',
          },
        },
      };

      mockAdminApi.createAdmin.mockRejectedValue(error);

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

      result.current.mutate({
        email: 'newadmin@example.com',
        role: 'admin',
      });

      await waitFor(() => expect(result.current.isError).toBe(true));

      expect(toast.error).toHaveBeenCalledWith('Admin already exists');
    });
  });

  describe('useRevokeAdmin', () => {
    it('should revoke admin and show success toast', async () => {
      mockAdminApi.revokeAdmin.mockResolvedValue();

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

      result.current.mutate('auth0|123');

      await waitFor(() => expect(result.current.isSuccess).toBe(true));

      expect(mockAdminApi.revokeAdmin).toHaveBeenCalledWith('auth0|123');
      expect(toast.success).toHaveBeenCalledWith('Admin revoked successfully');
    });
  });

  describe('useReinstateAdmin', () => {
    it('should reinstate admin and show success toast', async () => {
      mockAdminApi.reinstateAdmin.mockResolvedValue();

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

      result.current.mutate('auth0|123');

      await waitFor(() => expect(result.current.isSuccess).toBe(true));

      expect(mockAdminApi.reinstateAdmin).toHaveBeenCalledWith('auth0|123');
      expect(toast.success).toHaveBeenCalledWith('Admin reinstated successfully');
    });
  });
});
