import { beforeEach, describe, expect, it, vi } from 'vitest';
import {
  createOwnerWithOrganization,
  createUser,
  deleteUser,
  linkGuardianStudent,
  listUsers,
  updateUser,
} from '@/shared/api/users';
import { apiRequest } from '@/shared/api/httpClient';

vi.mock('@/shared/api/httpClient', () => ({
  apiRequest: vi.fn(),
}));

describe('users API', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('lists users with filters', async () => {
    vi.mocked(apiRequest).mockResolvedValueOnce({ rows: [] });

    await listUsers({
      query: 'emily',
      app_role: 'role-1',
      classId: 'class-1',
      campusId: 'campus-1',
      limit: 25,
      page: 2,
      field: 'name',
      sort: 'asc',
    });

    expect(apiRequest).toHaveBeenCalledWith('/users?query=emily&app_role=role-1&classId=class-1&campusId=campus-1&limit=25&page=2&field=name&sort=asc');
  });

  it('creates users and normalizes boolean CRUD responses', async () => {
    vi.mocked(apiRequest).mockResolvedValueOnce(true);

    await expect(createUser({ email: 'user@example.com' })).resolves.toEqual({ id: null });

    expect(apiRequest).toHaveBeenCalledWith('/users', {
      method: 'POST',
      body: { data: { email: 'user@example.com' } },
    });
  });

  it('creates owners with organizations', async () => {
    vi.mocked(apiRequest).mockResolvedValueOnce({ id: 'user-1' });

    await createOwnerWithOrganization({ email: 'owner@example.com' });

    expect(apiRequest).toHaveBeenCalledWith('/users/owner-with-organization', {
      method: 'POST',
      body: { data: { email: 'owner@example.com' } },
    });
  });

  it('updates and deletes users', async () => {
    vi.mocked(apiRequest).mockResolvedValue({});

    await updateUser('user-1', { firstName: 'Alex' });
    await deleteUser('user-1');

    expect(apiRequest).toHaveBeenNthCalledWith(1, '/users/user-1', {
      method: 'PUT',
      body: { id: 'user-1', data: { firstName: 'Alex' } },
    });
    expect(apiRequest).toHaveBeenNthCalledWith(2, '/users/user-1', { method: 'DELETE' });
  });

  it('links guardians to students', async () => {
    vi.mocked(apiRequest).mockResolvedValueOnce({});

    await linkGuardianStudent('guardian-1', 'student-1');

    expect(apiRequest).toHaveBeenCalledWith('/guardian_students', {
      method: 'POST',
      body: { data: { guardianId: 'guardian-1', studentId: 'student-1' } },
    });
  });
});
