import { renderHook, act } from '@testing-library/react';
import { vi, describe, it, expect, beforeEach } from 'vitest';

const { mockInvoke } = vi.hoisted(() => ({
  mockInvoke: vi.fn(),
}));

vi.mock('../../../lib/supabase', () => ({
  supabase: {
    functions: {
      invoke: mockInvoke,
    },
  },
}));

import { useAdminUsers } from '../useAdminUsers';

describe('useAdminUsers', () => {
  beforeEach(() => vi.clearAllMocks());

  it('starts with users: [], loading: true, error: null', () => {
    mockInvoke.mockReturnValue(new Promise(() => {}));
    const { result } = renderHook(() => useAdminUsers());
    expect(result.current.users).toEqual([]);
    expect(result.current.loading).toBe(true);
    expect(result.current.error).toBe(null);
  });

  it('fetches and sets users on mount', async () => {
    const userList = [
      { id: '1', email: 'a@example.com', created_at: '2024-01-01', last_sign_in_at: null },
      { id: '2', email: 'b@example.com', created_at: '2024-01-02', last_sign_in_at: null },
    ];
    mockInvoke.mockResolvedValue({ data: userList, error: null });
    const { result } = renderHook(() => useAdminUsers());
    await act(async () => {});
    expect(result.current.loading).toBe(false);
    expect(result.current.users).toEqual(userList);
    expect(result.current.error).toBe(null);
  });

  it('sets error when fetch fails', async () => {
    mockInvoke.mockResolvedValue({ data: null, error: { message: 'Fetch failed' } });
    const { result } = renderHook(() => useAdminUsers());
    await act(async () => {});
    expect(result.current.loading).toBe(false);
    expect(result.current.error).toBe('Fetch failed');
    expect(result.current.users).toEqual([]);
  });

  it('inviteUser appends a user to state', async () => {
    const existingUser = { id: '1', email: 'a@example.com', created_at: '2024-01-01', last_sign_in_at: null };
    const newUser = { id: '2', email: 'b@example.com', created_at: '2024-01-03', last_sign_in_at: null };

    mockInvoke
      .mockResolvedValueOnce({ data: [existingUser], error: null })
      .mockResolvedValueOnce({ data: newUser, error: null });

    const { result } = renderHook(() => useAdminUsers());
    await act(async () => {});
    expect(result.current.users).toEqual([existingUser]);

    await act(async () => {
      await result.current.inviteUser('b@example.com');
    });
    expect(result.current.users).toEqual([existingUser, newUser]);
  });

  it('deleteUser removes a user from state', async () => {
    const existingUser = { id: '1', email: 'a@example.com', created_at: '2024-01-01', last_sign_in_at: null };
    const newUser = { id: '2', email: 'b@example.com', created_at: '2024-01-03', last_sign_in_at: null };

    mockInvoke
      .mockResolvedValueOnce({ data: [existingUser, newUser], error: null })
      .mockResolvedValueOnce({ data: {}, error: null });

    const { result } = renderHook(() => useAdminUsers());
    await act(async () => {});
    expect(result.current.users).toEqual([existingUser, newUser]);

    await act(async () => {
      await result.current.deleteUser('1');
    });
    expect(result.current.users).toEqual([newUser]);
  });
});
