import { UserApi } from '../../api/userApi';
import * as sinon from 'sinon';

describe('UserApi Unit Test', () => {
    let userApiStub: sinon.SinonStubbedInstance<UserApi>;

    beforeEach(() => {
        // Create a stub instance for the UsersApi
        userApiStub = sinon.createStubInstance(UserApi);

        userApiStub.createUser = sinon.stub().resolves({ userId: 'user_id' });
        userApiStub.updateUser = sinon.stub().resolves({
            success: true,
            message: 'User updated successfully',
        });
    });

    afterEach(() => {
        sinon.restore();
    });

    it('should mock and verify createUser call', async () => {
        const mockUserCreated = {
            userId: 'user_id',
        };

        const userData = {
            name: 'New User',
            email: 'newuser@example.com',
            role: 'Admin',
        };

        userApiStub.createUser.resolves(mockUserCreated);

        const result = await userApiStub.createUser(userData);

        expect(result).toBeDefined();
        expect(result.userId).toBe('user_id');

        sinon.assert.calledOnceWithExactly(userApiStub.createUser, userData);
    });

    it('should mock and verify updateUser call', async () => {
        const mockUpdatedUser = {
            success: true,
            message: 'User updated successfully',
        };
    
        const userId = 'user_id';
        const updatedUserData = {
            name: 'Updated User',
            email: 'updateduser@example.com',
            role: 'Manager',
        };
    
        userApiStub.updateUser.resolves(mockUpdatedUser);
    
        const result = await userApiStub.updateUser(userId, updatedUserData);
    
        expect(result).toBeDefined();
        expect(result.success).toBe(true);
        expect(result.message).toBe('User updated successfully');
    
        sinon.assert.calledOnceWithExactly(
            userApiStub.updateUser,
            userId,
            updatedUserData
        );
    });

    it('should mock and verify listUsers call', async () => {
        const mockListResponse = {
            users: [
                {
                    userId: 'user_1',
                    name: 'User One',
                    email: 'userone@example.com',
                    role: 'Admin',
                },
                {
                    userId: 'user_2',
                    name: 'User Two',
                    email: 'usertwo@example.com',
                    role: 'Manager',
                },
            ],
        };
    
        userApiStub.listUsers = sinon.stub().resolves(mockListResponse);
    
        const result = await userApiStub.listUsers();
    
        expect(result).toBeDefined();
        expect(Array.isArray(result.users)).toBe(true);
        expect(result.users.length).toBe(2);
        expect(result.users[0].name).toBe('User One');
        expect(result.users[1].role).toBe('Manager');
    
        sinon.assert.calledOnce(userApiStub.listUsers);
    });

    it('should mock and verify getUserDetails call', async () => {
        const mockUserDetails = {
            userId: 'user_1',
            name: 'User One',
            email: 'userone@example.com',
            role: 'Admin',
        };
    
        const userId = 'user_1';
    
        userApiStub.getUserDetails = sinon.stub().resolves(mockUserDetails);
    
        const result = await userApiStub.getUserDetails(userId);
    
        expect(result).toBeDefined();
        expect(result.userId).toBe('user_1');
        expect(result.name).toBe('User One');
        expect(result.email).toBe('userone@example.com');
        expect(result.role).toBe('Admin');
    
        sinon.assert.calledOnceWithExactly(userApiStub.getUserDetails, userId);
    });

    it('should mock and verify resendUserInvitation call', async () => {
        const mockResendResponse = {
            success: true,
            message: 'User invitation resent successfully',
        };
    
        const userId = 'user_1';
    
        userApiStub.resendUserInvitation = sinon.stub().resolves(mockResendResponse);
    
        const result = await userApiStub.resendUserInvitation(userId);
    
        expect(result).toBeDefined();
        expect(result.success).toBe(true);
        expect(result.message).toBe('User invitation resent successfully');
    
        sinon.assert.calledOnceWithExactly(userApiStub.resendUserInvitation, userId);
    });

    it('should mock and verify cancelUserInvitation call', async () => {
        const mockCancelResponse = {
            success: true,
            message: 'Invitation canceled successfully',
        };
    
        const userId = 'user_1';
    
        userApiStub.cancelUserInvitation = sinon.stub().resolves(mockCancelResponse);

        const result = await userApiStub.cancelUserInvitation(userId);
    
        expect(result).toBeDefined();
        expect(result.success).toBe(true);
        expect(result.message).toBe('Invitation canceled successfully');
    
        sinon.assert.calledOnceWithExactly(userApiStub.cancelUserInvitation, userId);
    });
});