// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.user;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.nullable;

import com.cloud.utils.Ternary;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.Role;
import org.apache.cloudstack.acl.RoleService;
import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.acl.ApiKeyPairPermissionVO;
import org.apache.cloudstack.acl.ApiKeyPairVO;
import org.apache.cloudstack.acl.RolePermission;
import org.apache.cloudstack.acl.RolePermissionEntity;
import org.apache.cloudstack.acl.RolePermissionVO;
import org.apache.cloudstack.acl.RoleVO;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd;

import org.apache.cloudstack.acl.apikeypair.ApiKeyPair;
import org.apache.cloudstack.acl.apikeypair.ApiKeyPairService;
import org.apache.cloudstack.acl.dao.ApiKeyPairDao;
import org.apache.cloudstack.acl.dao.ApiKeyPairPermissionsDao;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd;
import org.apache.cloudstack.api.command.admin.user.GetUserKeysCmd;
import org.apache.cloudstack.api.command.admin.user.ListUserKeysCmd;
import org.apache.cloudstack.api.command.admin.user.RegisterUserKeysCmd;
import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd;
import org.apache.cloudstack.api.response.UserTwoFactorAuthenticationSetupResponse;
import org.apache.cloudstack.auth.UserAuthenticator;
import org.apache.cloudstack.auth.UserAuthenticator.ActionOnFailedAuthentication;
import org.apache.cloudstack.auth.UserTwoFactorAuthenticator;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.resourcedetail.UserDetailVO;
import org.apache.cloudstack.webhook.WebhookHelper;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;

import com.cloud.acl.DomainChecker;
import com.cloud.api.auth.SetupUserTwoFactorAuthenticationCmd;
import com.cloud.domain.Domain;
import com.cloud.domain.DomainVO;
import com.cloud.event.ActionEventUtils;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.projects.Project;
import com.cloud.projects.ProjectAccountVO;
import com.cloud.user.Account.State;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.UserVmManagerImpl;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.snapshot.VMSnapshotVO;

public class AccountManagerImplTest extends AccountManagentImplTestBase {

    @Mock
    private UserVmManagerImpl _vmMgr;
    @Mock
    private AccountVO callingAccount;
    @Mock
    private DomainChecker domainChecker;
    @Mock
    private AccountService accountService;
    @Mock
    private GetUserKeysCmd _getkeyscmd;
    @Mock
    private ListUserKeysCmd listUserKeysCmd;
    @Mock
    private User _user;
    @Mock
    private UserAccountVO userAccountVO;

    @Mock
    private UpdateUserCmd UpdateUserCmdMock;

    @Mock
    private UpdateAccountCmd UpdateAccountCmdMock;

    private final long userVoIdMock = 111L;
    @Mock
    private UserVO userVoMock;

    @Mock
    private ApiKeyPairService apiKeyPairService;

    @Mock
    private ApiKeyPairVO apiKeyPairVOMock;

    @Mock
    private Pair<List<ApiKeyPairVO>, Integer> pairMock;

    private final long accountMockId = 100L;

    @Mock
    private Account accountMock;

    @Mock
    private DomainVO domainVoMock;

    @Mock
    private AccountVO accountVoMock;
    @Mock
    private AccountVO _systemAccount;

    @Mock
    private ProjectAccountVO projectAccountVO;
    @Mock
    private Project project;

    @Mock
    PasswordPolicyImpl passwordPolicyMock;

    @Mock
    ConfigKey<Boolean> enableUserTwoFactorAuthenticationMock;

    @Mock
    ConfigKey<Boolean> allowOperationsOnUsersInSameAccountMock;

    @Mock
    RoleService roleService;

    @Mock
    ApiKeyPairPermissionsDao apiKeyPairPermissionsDaoMock;

    @Mock
    ApiKeyPairDao apiKeyPairDaoMock;

    @Mock
    RegisterUserKeysCmd registerCmdMock;

    @Before
    public void setUp() throws Exception {
        enableUserTwoFactorAuthenticationMock = Mockito.mock(ConfigKey.class);
        accountManagerImpl.enableUserTwoFactorAuthentication = enableUserTwoFactorAuthenticationMock;

        allowOperationsOnUsersInSameAccountMock = Mockito.mock(ConfigKey.class);
        accountManagerImpl.allowOperationsOnUsersInSameAccount = allowOperationsOnUsersInSameAccountMock;
    }

    @Before
    public void beforeTest() {
        Mockito.doReturn(accountMockId).when(accountMock).getId();
        Mockito.doReturn(accountMock).when(accountManagerImpl).getCurrentCallingAccount();

        Mockito.doReturn(accountMockId).when(userVoMock).getAccountId();

        Mockito.doReturn(userVoIdMock).when(userVoMock).getId();

        Mockito.lenient().doNothing().when(accountManagerImpl).checkRoleEscalation(accountMock, accountMock);
        Mockito.doReturn(accountMockId).when(accountVoMock).getId();

        Mockito.when(apiKeyPairDaoMock.persist(Mockito.any())).thenAnswer(i -> {
            ApiKeyPairVO keyPair = (ApiKeyPairVO) i.getArguments()[0];
            keyPair.setId(1L);
            return keyPair;
        });
    }

    @Test
    public void disableAccountNotexisting() throws ConcurrentOperationException, ResourceUnavailableException {
        Mockito.when(_accountDao.findById(42L)).thenReturn(null);
        Assert.assertTrue(accountManagerImpl.disableAccount(42));
    }

    @Test
    public void disableAccountDisabled() throws ConcurrentOperationException, ResourceUnavailableException {
        AccountVO disabledAccount = new AccountVO();
        disabledAccount.setState(State.DISABLED);
        Mockito.when(_accountDao.findById(42L)).thenReturn(disabledAccount);
        Assert.assertTrue(accountManagerImpl.disableAccount(42));
    }

    @Test
    public void disableAccount() throws ConcurrentOperationException, ResourceUnavailableException {
        AccountVO account = new AccountVO();
        account.setState(State.ENABLED);
        Mockito.when(_accountDao.findById(42L)).thenReturn(account);
        Mockito.when(_accountDao.createForUpdate()).thenReturn(new AccountVO());
        Mockito.when(_accountDao.update(Mockito.eq(42L), Mockito.any(AccountVO.class))).thenReturn(true);
        Mockito.when(_vmDao.listByAccountId(42L)).thenReturn(Arrays.asList(Mockito.mock(VMInstanceVO.class)));
        Assert.assertTrue(accountManagerImpl.disableAccount(42));
        Mockito.verify(_accountDao, Mockito.atLeastOnce()).update(Mockito.eq(42L), Mockito.any(AccountVO.class));
    }

    @Test
    public void deleteUserAccount() {
        AccountVO account = new AccountVO();
        account.setId(42L);
        DomainVO domain = new DomainVO();
        Mockito.when(_accountDao.findById(42L)).thenReturn(account);
        Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.any(Account.class), Mockito.isNull(), Mockito.anyBoolean(), Mockito.any(Account.class));
        Mockito.when(_accountDao.remove(42L)).thenReturn(true);
        Mockito.when(_configMgr.releaseAccountSpecificVirtualRanges(account)).thenReturn(true);
        Mockito.lenient().when(_domainMgr.getDomain(Mockito.anyLong())).thenReturn(domain);
        Mockito.lenient().when(securityChecker.checkAccess(Mockito.any(Account.class), Mockito.any(Domain.class))).thenReturn(true);
        Mockito.when(_vmSnapshotDao.listByAccountId(Mockito.anyLong())).thenReturn(new ArrayList<VMSnapshotVO>());
        Mockito.when(_autoscaleMgr.deleteAutoScaleVmGroupsByAccount(account)).thenReturn(true);

        List<SSHKeyPairVO> sshkeyList = new ArrayList<SSHKeyPairVO>();
        SSHKeyPairVO sshkey = new SSHKeyPairVO();
        sshkey.setId(1L);
        sshkeyList.add(sshkey);
        Mockito.when(_sshKeyPairDao.listKeyPairs(Mockito.anyLong(), Mockito.anyLong())).thenReturn(sshkeyList);
        Mockito.when(_sshKeyPairDao.remove(Mockito.anyLong())).thenReturn(true);
        Mockito.when(userDataDao.removeByAccountId(Mockito.anyLong())).thenReturn(222);
        Mockito.when(sslCertDao.removeByAccountId(Mockito.anyLong())).thenReturn(333);
        Mockito.when(kmsManager.deleteKMSKeysByAccountId(Mockito.anyLong())).thenReturn(true);
        Mockito.doNothing().when(accountManagerImpl).deleteWebhooksForAccount(Mockito.anyLong());
        Mockito.doNothing().when(accountManagerImpl).verifyCallerPrivilegeForUserOrAccountOperations((Account) any());

        Assert.assertTrue(accountManagerImpl.deleteUserAccount(42L));
        // assert that this was a clean delete
        Mockito.verify(_accountDao, Mockito.never()).markForCleanup(Mockito.eq(42L));
    }

    @Test
    public void deleteUserAccountCleanup() {
        AccountVO account = new AccountVO();
        account.setId(42L);
        DomainVO domain = new DomainVO();
        Mockito.when(_accountDao.findById(42L)).thenReturn(account);
        Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.any(Account.class), Mockito.isNull(), Mockito.anyBoolean(), Mockito.any(Account.class));
        Mockito.when(_accountDao.remove(42L)).thenReturn(true);
        Mockito.when(_configMgr.releaseAccountSpecificVirtualRanges(account)).thenReturn(true);
        Mockito.when(_userVmDao.listByAccountId(42L)).thenReturn(Arrays.asList(Mockito.mock(UserVmVO.class)));
        Mockito.when(_vmMgr.expunge(Mockito.any(UserVmVO.class))).thenReturn(false);
        Mockito.lenient().when(_domainMgr.getDomain(Mockito.anyLong())).thenReturn(domain);
        Mockito.lenient().when(securityChecker.checkAccess(Mockito.any(Account.class), Mockito.any(Domain.class))).thenReturn(true);
        Mockito.doNothing().when(accountManagerImpl).deleteWebhooksForAccount(Mockito.anyLong());
        Mockito.doNothing().when(accountManagerImpl).verifyCallerPrivilegeForUserOrAccountOperations((Account) any());

        Assert.assertTrue(accountManagerImpl.deleteUserAccount(42L));
        // assert that this was NOT a clean delete
        Mockito.verify(_accountDao, Mockito.atLeastOnce()).markForCleanup(Mockito.eq(42L));
    }

    @Test (expected = InvalidParameterValueException.class)
    public void deleteUserAccountTestIfAccountIdIsEqualToCallerIdShouldThrowException() {
        try (MockedStatic<CallContext> callContextMocked = Mockito.mockStatic(CallContext.class)) {
            CallContext callContextMock = Mockito.mock(CallContext.class);
            callContextMocked.when(CallContext::current).thenReturn(callContextMock);
            long accountId = 1L;

            Mockito.doReturn(accountVoMock).when(callContextMock).getCallingAccount();
            Mockito.doReturn(accountVoMock).when(_accountDao).findById(Mockito.anyLong());
            Mockito.doReturn(domainVoMock).when(_domainDao).findById(Mockito.anyLong());
            Mockito.doReturn(1L).when(accountVoMock).getId();

            accountManagerImpl.deleteUserAccount(accountId);
        }
    }

    @Test
    public void deleteUserAccountTestIfAccountIdIsNotEqualToCallerAccountIdShouldNotThrowException() {
        try (MockedStatic<CallContext> callContextMocked = Mockito.mockStatic(CallContext.class)) {
            CallContext callContextMock = Mockito.mock(CallContext.class);
            callContextMocked.when(CallContext::current).thenReturn(callContextMock);
            long accountId = 1L;

            Mockito.doReturn(accountVoMock).when(callContextMock).getCallingAccount();
            Mockito.doReturn(accountVoMock).when(_accountDao).findById(Mockito.anyLong());
            Mockito.doReturn(2L).when(accountVoMock).getId();
            Mockito.doReturn(true).when(accountManagerImpl).isDeleteNeeded(Mockito.any(), Mockito.anyLong(), Mockito.any());
            Mockito.doReturn(new ArrayList<Long>()).when(_projectAccountDao).listAdministratedProjectIds(Mockito.anyLong());
            Mockito.doNothing().when(accountManagerImpl).verifyCallerPrivilegeForUserOrAccountOperations((Account) any());

            accountManagerImpl.deleteUserAccount(accountId);
        }
    }

    @Test (expected = InvalidParameterValueException.class)
    public void deleteUserTestIfUserIdIsEqualToCallerIdShouldThrowException() {
        try (MockedStatic<CallContext> callContextMocked = Mockito.mockStatic(CallContext.class)) {
            DeleteUserCmd cmd = Mockito.mock(DeleteUserCmd.class);
            CallContext callContextMock = Mockito.mock(CallContext.class);
            callContextMocked.when(CallContext::current).thenReturn(callContextMock);

            Mockito.doReturn(userVoMock).when(callContextMock).getCallingUser();
            Mockito.doReturn(1L).when(cmd).getId();
            Mockito.doReturn(userVoMock).when(accountManagerImpl).getValidUserVO(Mockito.anyLong());
            Mockito.doReturn(accountVoMock).when(_accountDao).findById(Mockito.anyLong());
            Mockito.doReturn(domainVoMock).when(_domainDao).findById(Mockito.anyLong());
            Mockito.doReturn(1L).when(userVoMock).getId();

            accountManagerImpl.deleteUser(cmd);
        }
    }

    @Test
    public void deleteUserTestIfUserIdIsNotEqualToCallerIdShouldNotThrowException() {
        try (MockedStatic<CallContext> callContextMocked = Mockito.mockStatic(CallContext.class)) {
            DeleteUserCmd cmd = Mockito.mock(DeleteUserCmd.class);
            CallContext callContextMock = Mockito.mock(CallContext.class);
            callContextMocked.when(CallContext::current).thenReturn(callContextMock);

            Mockito.doReturn(userVoMock).when(callContextMock).getCallingUser();
            Mockito.doReturn(1L).when(cmd).getId();
            Mockito.doReturn(userVoMock).when(accountManagerImpl).getValidUserVO(Mockito.anyLong());
            Mockito.doReturn(accountVoMock).when(_accountDao).findById(Mockito.anyLong());
            Mockito.doReturn(2L).when(userVoMock).getId();

            Mockito.doNothing().when(accountManagerImpl).checkAccountAndAccess(Mockito.any(), Mockito.any());
            Mockito.doNothing().when(accountManagerImpl).verifyCallerPrivilegeForUserOrAccountOperations(userVoMock);
            Mockito.doNothing().when(accountManagerImpl).removeUserApiKeys(Mockito.anyLong());
            accountManagerImpl.deleteUser(cmd);
        }
    }

    @Test
    public void testAuthenticateUser() throws UnknownHostException {
        Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication> successAuthenticationPair = new Pair<>(true, null);
        Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication> failureAuthenticationPair = new Pair<>(false,
                UserAuthenticator.ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT);

        UserAccountVO userAccountVO = new UserAccountVO();
        userAccountVO.setSource(User.Source.UNKNOWN);
        userAccountVO.setState(Account.State.DISABLED.toString());
        Mockito.when(userAccountDao.getUserAccount("test", 1L)).thenReturn(userAccountVO);
        Mockito.when(userAuthenticator.authenticate("test", "fail", 1L, new HashMap<>())).thenReturn(failureAuthenticationPair);
        Mockito.lenient().when(userAuthenticator.authenticate("test", null, 1L, new HashMap<>())).thenReturn(successAuthenticationPair);
        Mockito.lenient().when(userAuthenticator.authenticate("test", "", 1L, new HashMap<>())).thenReturn(successAuthenticationPair);
        Mockito.when(userAuthenticator.getName()).thenReturn("test");

        //Test for incorrect password. authentication should fail
        UserAccount userAccount = accountManagerImpl.authenticateUser("test", "fail", 1L, InetAddress.getByName("127.0.0.1"), new HashMap<>());
        Assert.assertNull(userAccount);

        //Test for null password. authentication should fail
        userAccount = accountManagerImpl.authenticateUser("test", null, 1L, InetAddress.getByName("127.0.0.1"), new HashMap<>());
        Assert.assertNull(userAccount);

        //Test for empty password. authentication should fail
        userAccount = accountManagerImpl.authenticateUser("test", "", 1L, InetAddress.getByName("127.0.0.1"), new HashMap<>());
        Assert.assertNull(userAccount);

        //Verifying that the authentication method is only called when password is specified
        Mockito.verify(userAuthenticator, Mockito.times(1)).authenticate("test", "fail", 1L, new HashMap<>());
        Mockito.verify(userAuthenticator, Mockito.never()).authenticate("test", null, 1L, null);
        Mockito.verify(userAuthenticator, Mockito.never()).authenticate("test", "", 1L, null);
    }

    @Test(expected = PermissionDeniedException.class)
    public void testGetUserCmd() {
        CallContext.register(callingUser, callingAccount); // Calling account is user account i.e normal account
        Mockito.when(_getkeyscmd.getId()).thenReturn(1L);
        Mockito.when(accountManagerImpl.getActiveUser(1L)).thenReturn(userVoMock);

        Mockito.lenient().when(callingUser.getAccountId()).thenReturn(1L);
        Mockito.lenient().when(_accountDao.findById(1L)).thenReturn(callingAccount);

        Mockito.lenient().when(accountService.isNormalUser(Mockito.anyLong())).thenReturn(Boolean.TRUE);
        Mockito.lenient().when(accountMock.getAccountId()).thenReturn(2L);

        accountManagerImpl.getKeys(_getkeyscmd);
    }

    @Test(expected = PermissionDeniedException.class)
    public void testGetUserKeysCmdDomainAdminRootAdminUser() {
        CallContext.register(callingUser, callingAccount);
        Mockito.when(_getkeyscmd.getId()).thenReturn(2L);
        Mockito.when(accountManagerImpl.getActiveUser(2L)).thenReturn(userVoMock);
        Mockito.when(userVoMock.getAccountId()).thenReturn(2L);

        // Queried account - admin account
        AccountVO adminAccountMock = Mockito.mock(AccountVO.class);
        Mockito.when(_accountDao.findByIdIncludingRemoved(2L)).thenReturn(adminAccountMock);
        Mockito.lenient().when(accountService.isRootAdmin(2L)).thenReturn(true);
        Mockito.lenient().when(securityChecker.checkAccess(Mockito.any(Account.class),
                Mockito.nullable(ControlledEntity.class), Mockito.nullable(AccessType.class), Mockito.anyString())).thenReturn(true);

        // Calling account is domain admin of the ROOT domain
        Mockito.lenient().when(callingAccount.getType()).thenReturn(Account.Type.DOMAIN_ADMIN);
        Mockito.lenient().when(callingAccount.getDomainId()).thenReturn(Domain.ROOT_DOMAIN);

        Mockito.lenient().when(callingUser.getAccountId()).thenReturn(2L);
        Mockito.lenient().when(_accountDao.findById(2L)).thenReturn(callingAccount);

        Mockito.lenient().when(accountService.isDomainAdmin(Mockito.anyLong())).thenReturn(Boolean.TRUE);
        Mockito.lenient().when(accountMock.getAccountId()).thenReturn(2L);

        accountManagerImpl.getKeys(_getkeyscmd);
    }

    @Test
    public void testPreventRootDomainAdminAccessToRootAdminKeysNormalUser() {
        User user = Mockito.mock(User.class);
        ControlledEntity entity = Mockito.mock(ControlledEntity.class);
        Mockito.when(user.getAccountId()).thenReturn(1L);
        AccountVO account = Mockito.mock(AccountVO.class);
        Mockito.when(account.getType()).thenReturn(Account.Type.NORMAL);
        Mockito.when(_accountDao.findById(1L)).thenReturn(account);
        accountManagerImpl.preventRootDomainAdminAccessToRootAdminKeys(user, entity);
        Mockito.verify(accountManagerImpl, Mockito.never()).isRootAdmin(Mockito.anyLong());
    }

    @Test(expected = PermissionDeniedException.class)
    public void testPreventRootDomainAdminAccessToRootAdminKeysRootDomainAdminUser() {
        User user = Mockito.mock(User.class);
        ControlledEntity entity = Mockito.mock(ControlledEntity.class);
        Mockito.when(user.getAccountId()).thenReturn(1L);
        AccountVO account = Mockito.mock(AccountVO.class);
        Mockito.when(account.getType()).thenReturn(Account.Type.DOMAIN_ADMIN);
        Mockito.when(account.getDomainId()).thenReturn(Domain.ROOT_DOMAIN);
        Mockito.when(_accountDao.findById(1L)).thenReturn(account);
        Mockito.when(entity.getAccountId()).thenReturn(1L);
        Mockito.lenient().when(securityChecker.checkAccess(Mockito.any(Account.class),
                Mockito.nullable(ControlledEntity.class), Mockito.nullable(AccessType.class), Mockito.anyString())).thenReturn(true);
        accountManagerImpl.preventRootDomainAdminAccessToRootAdminKeys(user, entity);
    }

    @Test
    public void updateUserTestTimeZoneAndEmailNull() {
        Mockito.when(userVoMock.getAccountId()).thenReturn(10L);
        Mockito.doReturn(accountMock).when(accountManagerImpl).getAccount(10L);
        Mockito.when(accountMock.getAccountId()).thenReturn(10L);
        Mockito.doReturn(false).when(accountManagerImpl).isRootAdmin(10L);
        Mockito.lenient().when(accountManagerImpl.getRoleType(Mockito.eq(accountMock))).thenReturn(RoleType.User);

        prepareMockAndExecuteUpdateUserTest(0);
    }

    @Test
    public void updateUserTestTimeZoneAndEmailNotNull() {
        Mockito.when(UpdateUserCmdMock.getEmail()).thenReturn("email");
        Mockito.when(UpdateUserCmdMock.getTimezone()).thenReturn("timezone");
        Mockito.when(userVoMock.getAccountId()).thenReturn(10L);
        Mockito.doReturn(accountMock).when(accountManagerImpl).getAccount(10L);
        Mockito.when(accountMock.getAccountId()).thenReturn(10L);
        Mockito.doReturn(false).when(accountManagerImpl).isRootAdmin(10L);
        Mockito.lenient().when(accountManagerImpl.getRoleType(Mockito.eq(accountMock))).thenReturn(RoleType.User);
        prepareMockAndExecuteUpdateUserTest(1);
    }

    @Test(expected = CloudRuntimeException.class)
    public void updateUserTestPwdChangeDisabledUser() {
        Mockito.when(userVoMock.getState()).thenReturn(State.DISABLED);
        updateUserPwdChange();
    }

    @Test(expected = CloudRuntimeException.class)
    public void updateUserTestPwdChangeLockedUser() {
        Mockito.when(userVoMock.getState()).thenReturn(State.LOCKED);
        updateUserPwdChange();
    }

    @Test(expected = CloudRuntimeException.class)
    public void updateUserTestPwdChangeDisabledAccount() {
        Mockito.when(userVoMock.getState()).thenReturn(State.ENABLED);
        Mockito.when(accountMock.getState()).thenReturn(State.LOCKED);
        updateUserPwdChange();
    }

    @Test
    public void testUpdateUserTestPwdChange() {
        Mockito.when(userVoMock.getState()).thenReturn(State.ENABLED);
        Mockito.when(accountMock.getState()).thenReturn(State.ENABLED);
        updateUserPwdChange();
    }

    private void updateUserPwdChange() {
        Mockito.doReturn(true).when(UpdateUserCmdMock).isPasswordChangeRequired();
        Mockito.when(userVoMock.getAccountId()).thenReturn(10L);
        Mockito.doReturn(accountMock).when(accountManagerImpl).getAccount(10L);
        Mockito.when(accountMock.getAccountId()).thenReturn(10L);
        Mockito.doReturn(false).when(accountManagerImpl).isRootAdmin(10L);
        Mockito.lenient().when(accountManagerImpl.getRoleType(Mockito.eq(accountMock))).thenReturn(RoleType.User);
        Mockito.when(callingUser.getAccountId()).thenReturn(1L);
        Mockito.doReturn(true).when(accountManagerImpl).isRootAdmin(1L);
        prepareMockAndExecuteUpdateUserTest(0);
    }

    private void prepareMockAndExecuteUpdateUserTest(int numberOfExpectedCallsForSetEmailAndSetTimeZone) {
        Mockito.doReturn("password").when(UpdateUserCmdMock).getPassword();
        Mockito.doReturn("newpassword").when(UpdateUserCmdMock).getCurrentPassword();
        Mockito.doReturn(userVoMock).when(accountManagerImpl).retrieveAndValidateUser(UpdateUserCmdMock);
        Mockito.doReturn(accountMock).when(accountManagerImpl).retrieveAndValidateAccount(userVoMock);

        Mockito.doNothing().when(accountManagerImpl).validateAndUpdateFirstNameIfNeeded(UpdateUserCmdMock, userVoMock);
        Mockito.doNothing().when(accountManagerImpl).validateAndUpdateLastNameIfNeeded(UpdateUserCmdMock, userVoMock);
        Mockito.doNothing().when(accountManagerImpl).validateAndUpdateUsernameIfNeeded(UpdateUserCmdMock, userVoMock, accountMock);
        Mockito.doNothing().when(accountManagerImpl).validateUserPasswordAndUpdateIfNeeded(Mockito.anyString(), Mockito.eq(userVoMock), Mockito.anyString(), Mockito.eq(false));

        Mockito.doReturn(true).when(userDaoMock).update(Mockito.anyLong(), Mockito.eq(userVoMock));
        Mockito.doReturn(Mockito.mock(UserAccountVO.class)).when(userAccountDao).findById(Mockito.anyLong());
        Mockito.doNothing().when(accountManagerImpl).checkAccess(nullable(User.class), nullable(Account.class));

        accountManagerImpl.updateUser(UpdateUserCmdMock);

        Mockito.lenient().doNothing().when(accountManagerImpl).checkRoleEscalation(accountMock, accountMock);

        InOrder inOrder = Mockito.inOrder(userVoMock, accountManagerImpl, userDaoMock, userAccountDao);

        inOrder.verify(accountManagerImpl).retrieveAndValidateUser(UpdateUserCmdMock);
        inOrder.verify(accountManagerImpl).retrieveAndValidateAccount(userVoMock);
        inOrder.verify(accountManagerImpl).validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);

        inOrder.verify(accountManagerImpl).validateAndUpdateFirstNameIfNeeded(UpdateUserCmdMock, userVoMock);
        inOrder.verify(accountManagerImpl).validateAndUpdateLastNameIfNeeded(UpdateUserCmdMock, userVoMock);
        inOrder.verify(accountManagerImpl).validateAndUpdateUsernameIfNeeded(UpdateUserCmdMock, userVoMock, accountMock);
        inOrder.verify(accountManagerImpl).validateUserPasswordAndUpdateIfNeeded(UpdateUserCmdMock.getPassword(), userVoMock, UpdateUserCmdMock.getCurrentPassword(), false);

        inOrder.verify(userVoMock, Mockito.times(numberOfExpectedCallsForSetEmailAndSetTimeZone)).setEmail(Mockito.anyString());
        inOrder.verify(userVoMock, Mockito.times(numberOfExpectedCallsForSetEmailAndSetTimeZone)).setTimezone(Mockito.anyString());

        inOrder.verify(userDaoMock).update(Mockito.anyLong(), Mockito.eq(userVoMock));
        inOrder.verify(userAccountDao).findById(Mockito.anyLong());
    }

    @Test(expected = InvalidParameterValueException.class)
    public void retrieveAndValidateUserTestNoUserFound() {
        Mockito.doReturn(null).when(userDaoMock).getUser(Mockito.anyLong());

        accountManagerImpl.retrieveAndValidateUser(UpdateUserCmdMock);
    }

    @Test
    public void retrieveAndValidateUserTestUserIsFound() {
        Mockito.doReturn(userVoMock).when(userDaoMock).getUser(Mockito.anyLong());

        UserVO receivedUser = accountManagerImpl.retrieveAndValidateUser(UpdateUserCmdMock);

        Assert.assertEquals(userVoMock, receivedUser);
    }

    @Test
    public void validateAndUpdateApiAndSecretKeyIfNeededTestNoKeys() {
        accountManagerImpl.validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);

        Mockito.verify(apiKeyPairDaoMock, Mockito.times(0)).getLastApiKeyCreatedByUser(Mockito.anyLong());
        Mockito.verify(accountManagerImpl, Mockito.times(0)).findUserByApiKey(Mockito.anyString());
    }

    @Test(expected = InvalidParameterValueException.class)
    public void validateAndUpdateApiAndSecretKeyIfNeededTestOnlyApiKeyInformed() {
        Mockito.doReturn("apiKey").when(UpdateUserCmdMock).getApiKey();

        accountManagerImpl.validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void validateAndUpdateApiAndSecretKeyIfNeededTestOnlySecretKeyInformed() {
        Mockito.doReturn("secretKey").when(UpdateUserCmdMock).getSecretKey();

        accountManagerImpl.validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void validateAndUpdateApiAndSecretKeyIfNeededTestApiKeyAlreadyUsedBySomeoneElse() {
        String apiKey = "apiKey";
        Mockito.doReturn(apiKey).when(UpdateUserCmdMock).getApiKey();
        Mockito.doReturn("secretKey").when(UpdateUserCmdMock).getSecretKey();

        Mockito.doReturn(1L).when(userVoMock).getId();
        Mockito.doReturn(apiKeyPairVOMock).when(apiKeyPairDaoMock).getLastApiKeyCreatedByUser(1L);

        User otherUserMock = Mockito.mock(User.class);

        Ternary<User, Account, ApiKeyPair> pairUserAccountMock = new Ternary<User, Account, ApiKeyPair>(otherUserMock, Mockito.mock(Account.class), apiKeyPairVOMock);
        Mockito.doReturn(pairUserAccountMock).when(accountManagerImpl).findUserByApiKey(apiKey);

        accountManagerImpl.validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void validateAndUpdateApiAndSecretKeyIfNeededTestUserHasNoActiveApiKeyPair() {
        String apiKey = "apiKey";
        Mockito.doReturn(apiKey).when(UpdateUserCmdMock).getApiKey();
        Mockito.doReturn("secretKey").when(UpdateUserCmdMock).getSecretKey();
        Mockito.doReturn(1L).when(userVoMock).getId();
        accountManagerImpl.validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
    }

    @Test
    public void validateAndUpdateApiAndSecretKeyIfNeededTest() {
        String apiKey = "apiKey";
        Mockito.doReturn(apiKey).when(UpdateUserCmdMock).getApiKey();

        String secretKey = "secretKey";
        Mockito.doReturn(secretKey).when(UpdateUserCmdMock).getSecretKey();

        Mockito.doReturn(1L).when(userVoMock).getId();
        Mockito.doReturn(apiKeyPairVOMock).when(apiKeyPairDaoMock).getLastApiKeyCreatedByUser(1L);

        accountManagerImpl.validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);

        Mockito.verify(accountManagerImpl).findUserByApiKey(apiKey);
        Mockito.verify(apiKeyPairVOMock).setApiKey(apiKey);
        Mockito.verify(apiKeyPairVOMock).setSecretKey(secretKey);
    }

    @Test
    public void validateAndUpdateUserApiKeyAccess() {
        Mockito.doReturn("Enabled").when(UpdateUserCmdMock).getApiKeyAccess();
        try (MockedStatic<ActionEventUtils> eventUtils = Mockito.mockStatic(ActionEventUtils.class)) {
            Mockito.when(ActionEventUtils.onActionEvent(Mockito.anyLong(), Mockito.anyLong(),
                    Mockito.anyLong(),
                    Mockito.anyString(), Mockito.anyString(),
                    Mockito.anyLong(), Mockito.anyString())).thenReturn(1L);
            accountManagerImpl.validateAndUpdateUserApiKeyAccess(UpdateUserCmdMock, userVoMock);
        }

        Mockito.verify(userVoMock).setApiKeyAccess(true);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void validateAndUpdatUserApiKeyAccessInvalidParameter() {
        Mockito.doReturn("False").when(UpdateUserCmdMock).getApiKeyAccess();
        accountManagerImpl.validateAndUpdateUserApiKeyAccess(UpdateUserCmdMock, userVoMock);
    }

    @Test
    public void validateAndUpdateAccountApiKeyAccess() {
        Mockito.doReturn("Inherit").when(UpdateAccountCmdMock).getApiKeyAccess();
        try (MockedStatic<ActionEventUtils> eventUtils = Mockito.mockStatic(ActionEventUtils.class)) {
            Mockito.when(ActionEventUtils.onActionEvent(Mockito.anyLong(), Mockito.anyLong(),
                    Mockito.anyLong(),
                    Mockito.anyString(), Mockito.anyString(),
                    Mockito.anyLong(), Mockito.anyString())).thenReturn(1L);
            accountManagerImpl.validateAndUpdateAccountApiKeyAccess(UpdateAccountCmdMock, accountVoMock);
        }

        Mockito.verify(accountVoMock).setApiKeyAccess(null);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void validateAndUpdateAccountApiKeyAccessInvalidParameter() {
        Mockito.doReturn("False").when(UpdateAccountCmdMock).getApiKeyAccess();
        accountManagerImpl.validateAndUpdateAccountApiKeyAccess(UpdateAccountCmdMock, accountVoMock);
    }

    @Test(expected = CloudRuntimeException.class)
    public void retrieveAndValidateAccountTestAccountNotFound() {
        Mockito.doReturn(accountMockId).when(userVoMock).getAccountId();

        Mockito.doReturn(null).when(_accountDao).findById(accountMockId);

        accountManagerImpl.retrieveAndValidateAccount(userVoMock);
    }

    @Test
    public void retrieveAndValidateAccountTestAccountTypeEqualsProjectType() {
        Mockito.doReturn(accountMockId).when(userVoMock).getAccountId();
        Mockito.lenient().doReturn(Account.Type.PROJECT).when(accountMock).getType();
        Mockito.doReturn(callingAccount).when(_accountDao).findById(accountMockId);
        Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.any(Account.class), Mockito.any(AccessType.class), Mockito.anyBoolean(), Mockito.any(Account.class));

        accountManagerImpl.retrieveAndValidateAccount(userVoMock);
    }

    @Test
    public void retrieveAndValidateAccountTestAccountTypeEqualsSystemType() {
        Mockito.doReturn(Account.ACCOUNT_ID_SYSTEM).when(userVoMock).getAccountId();
        Mockito.doReturn(Account.ACCOUNT_ID_SYSTEM).when(accountMock).getId();
        Mockito.doReturn(callingAccount).when(_accountDao).findById(Account.ACCOUNT_ID_SYSTEM);
        accountManagerImpl.retrieveAndValidateAccount(userVoMock);
    }

    @Test
    public void retrieveAndValidateAccountTest() {
        Mockito.doReturn(accountMockId).when(userVoMock).getAccountId();
        Mockito.doReturn(callingAccount).when(_accountDao).findById(accountMockId);

        Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.eq(accountMock), Mockito.eq(AccessType.OperateEntry), Mockito.anyBoolean(), Mockito.any(Account.class));
        accountManagerImpl.retrieveAndValidateAccount(userVoMock);

        Mockito.verify(accountManagerImpl).getCurrentCallingAccount();
        Mockito.verify(accountManagerImpl).checkAccess(Mockito.eq(accountMock), Mockito.eq(AccessType.OperateEntry), Mockito.anyBoolean(), Mockito.any(Account.class));
    }

    @Test(expected = InvalidParameterValueException.class)
    public void validateAndUpdateFirstNameIfNeededTestFirstNameBlank() {
        Mockito.doReturn("   ").when(UpdateUserCmdMock).getFirstname();

        accountManagerImpl.validateAndUpdateFirstNameIfNeeded(UpdateUserCmdMock, userVoMock);
    }

    @Test
    public void validateAndUpdateFirstNameIfNeededTestFirstNameNull() {
        Mockito.doReturn(null).when(UpdateUserCmdMock).getFirstname();

        accountManagerImpl.validateAndUpdateFirstNameIfNeeded(UpdateUserCmdMock, userVoMock);

        Mockito.verify(userVoMock, Mockito.times(0)).setFirstname(Mockito.anyString());
    }

    @Test
    public void validateAndUpdateFirstNameIfNeededTest() {
        String firstname = "firstName";
        Mockito.doReturn(firstname).when(UpdateUserCmdMock).getFirstname();

        accountManagerImpl.validateAndUpdateFirstNameIfNeeded(UpdateUserCmdMock, userVoMock);

        Mockito.verify(userVoMock).setFirstname(firstname);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void validateAndUpdateLastNameIfNeededTestLastNameBlank() {
        Mockito.doReturn("   ").when(UpdateUserCmdMock).getLastname();

        accountManagerImpl.validateAndUpdateLastNameIfNeeded(UpdateUserCmdMock, userVoMock);
    }

    @Test
    public void validateAndUpdateLastNameIfNeededTestLastNameNull() {
        Mockito.doReturn(null).when(UpdateUserCmdMock).getLastname();

        accountManagerImpl.validateAndUpdateLastNameIfNeeded(UpdateUserCmdMock, userVoMock);

        Mockito.verify(userVoMock, Mockito.times(0)).setLastname(Mockito.anyString());
    }

    @Test
    public void validateAndUpdateLastNameIfNeededTest() {
        String lastName = "lastName";
        Mockito.doReturn(lastName).when(UpdateUserCmdMock).getLastname();

        accountManagerImpl.validateAndUpdateLastNameIfNeeded(UpdateUserCmdMock, userVoMock);

        Mockito.verify(userVoMock).setLastname(lastName);
    }

    @Test
    public void validateAndUpdateUsernameIfNeededTestNullUsername() {
        Mockito.doReturn(null).when(UpdateUserCmdMock).getUsername();

        accountManagerImpl.validateAndUpdateUsernameIfNeeded(UpdateUserCmdMock, userVoMock, accountMock);

        Mockito.verify(userVoMock, Mockito.times(0)).setUsername(Mockito.anyString());
    }

    @Test(expected = InvalidParameterValueException.class)
    public void validateAndUpdateUsernameIfNeededTestBlankUsername() {
        Mockito.doReturn("   ").when(UpdateUserCmdMock).getUsername();

        accountManagerImpl.validateAndUpdateUsernameIfNeeded(UpdateUserCmdMock, userVoMock, accountMock);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void validateAndUpdateUsernameIfNeededTestDuplicatedUserSameDomainThisUser() {
        long domanIdCurrentUser = 22L;

        String userName = "username";
        Mockito.doReturn(userName).when(UpdateUserCmdMock).getUsername();
        Mockito.lenient().doReturn(userName).when(userVoMock).getUsername();
        Mockito.doReturn(domanIdCurrentUser).when(accountMock).getDomainId();

        long userVoDuplicatedMockId = 67L;
        UserVO userVoDuplicatedMock = Mockito.mock(UserVO.class);
        Mockito.doReturn(userVoDuplicatedMockId).when(userVoDuplicatedMock).getId();

        long accountIdUserDuplicated = 98L;

        Mockito.doReturn(accountIdUserDuplicated).when(userVoDuplicatedMock).getAccountId();

        Account accountUserDuplicatedMock = Mockito.mock(AccountVO.class);
        Mockito.lenient().doReturn(accountIdUserDuplicated).when(accountUserDuplicatedMock).getId();
        Mockito.doReturn(domanIdCurrentUser).when(accountUserDuplicatedMock).getDomainId();

        List<UserVO> usersWithSameUserName = new ArrayList<>();
        usersWithSameUserName.add(userVoMock);
        usersWithSameUserName.add(userVoDuplicatedMock);

        Mockito.doReturn(usersWithSameUserName).when(userDaoMock).findUsersByName(userName);

        Mockito.lenient().doReturn(accountMock).when(_accountDao).findById(accountMockId);
        Mockito.doReturn(accountUserDuplicatedMock).when(_accountDao).findById(accountIdUserDuplicated);

        Mockito.doReturn(Mockito.mock(DomainVO.class)).when(_domainDao).findById(Mockito.anyLong());

        accountManagerImpl.validateAndUpdateUsernameIfNeeded(UpdateUserCmdMock, userVoMock, accountMock);
    }

    @Test
    public void validateAndUpdateUsernameIfNeededTestDuplicatedUserButInDifferentDomains() {
        long domanIdCurrentUser = 22L;

        String userName = "username";
        Mockito.doReturn(userName).when(UpdateUserCmdMock).getUsername();
        Mockito.lenient().doReturn(userName).when(userVoMock).getUsername();
        Mockito.doReturn(domanIdCurrentUser).when(accountMock).getDomainId();

        long userVoDuplicatedMockId = 67L;
        UserVO userVoDuplicatedMock = Mockito.mock(UserVO.class);
        Mockito.lenient().doReturn(userName).when(userVoDuplicatedMock).getUsername();
        Mockito.doReturn(userVoDuplicatedMockId).when(userVoDuplicatedMock).getId();

        long accountIdUserDuplicated = 98L;
        Mockito.doReturn(accountIdUserDuplicated).when(userVoDuplicatedMock).getAccountId();

        Account accountUserDuplicatedMock = Mockito.mock(AccountVO.class);
        Mockito.lenient().doReturn(accountIdUserDuplicated).when(accountUserDuplicatedMock).getId();
        Mockito.doReturn(45L).when(accountUserDuplicatedMock).getDomainId();

        List<UserVO> usersWithSameUserName = new ArrayList<>();
        usersWithSameUserName.add(userVoMock);
        usersWithSameUserName.add(userVoDuplicatedMock);

        Mockito.doReturn(usersWithSameUserName).when(userDaoMock).findUsersByName(userName);

        Mockito.lenient().doReturn(accountMock).when(_accountDao).findById(accountMockId);
        Mockito.doReturn(accountUserDuplicatedMock).when(_accountDao).findById(accountIdUserDuplicated);

        accountManagerImpl.validateAndUpdateUsernameIfNeeded(UpdateUserCmdMock, userVoMock, accountMock);

        Mockito.verify(userVoMock).setUsername(userName);
    }

    @Test
    public void validateAndUpdateUsernameIfNeededTestNoDuplicatedUserNames() {
        long domanIdCurrentUser = 22L;

        String userName = "username";
        Mockito.doReturn(userName).when(UpdateUserCmdMock).getUsername();
        Mockito.lenient().doReturn(userName).when(userVoMock).getUsername();
        Mockito.lenient().doReturn(domanIdCurrentUser).when(accountMock).getDomainId();

        List<UserVO> usersWithSameUserName = new ArrayList<>();

        Mockito.doReturn(usersWithSameUserName).when(userDaoMock).findUsersByName(userName);

        Mockito.lenient().doReturn(accountMock).when(_accountDao).findById(accountMockId);

        accountManagerImpl.validateAndUpdateUsernameIfNeeded(UpdateUserCmdMock, userVoMock, accountMock);

        Mockito.verify(userVoMock).setUsername(userName);
    }

    @Test
    public void valiateUserPasswordAndUpdateIfNeededTestPasswordNull() {
        accountManagerImpl.validateUserPasswordAndUpdateIfNeeded(null, userVoMock, null, false);

        Mockito.verify(userVoMock, Mockito.times(0)).setPassword(Mockito.anyString());
    }

    @Test(expected = InvalidParameterValueException.class)
    public void valiateUserPasswordAndUpdateIfNeededTestBlankPassword() {
        accountManagerImpl.validateUserPasswordAndUpdateIfNeeded("       ", userVoMock, null, false);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void valiateUserPasswordAndUpdateIfNeededTestNoAdminAndNoCurrentPasswordProvided() {
        Mockito.doReturn(accountMock).when(accountManagerImpl).getCurrentCallingAccount();
        Mockito.doReturn(false).when(accountManagerImpl).isRootAdmin(accountMockId);
        Mockito.doReturn(false).when(accountManagerImpl).isDomainAdmin(accountMockId);
        Mockito.lenient().doReturn(true).when(accountManagerImpl).isResourceDomainAdmin(accountMockId);

        Mockito.doReturn(accountMock).when(accountManagerImpl).getAccount(Mockito.anyLong());

        Mockito.lenient().doNothing().when(passwordPolicyMock).verifyIfPasswordCompliesWithPasswordPolicies(Mockito.anyString(), Mockito.anyString(), Mockito.anyLong());

        accountManagerImpl.validateUserPasswordAndUpdateIfNeeded("newPassword", userVoMock, "  ", false);
    }

    @Test(expected = CloudRuntimeException.class)
    public void valiateUserPasswordAndUpdateIfNeededTestNoUserAuthenticatorsConfigured() {
        Mockito.doReturn(accountMock).when(accountManagerImpl).getCurrentCallingAccount();
        Mockito.doReturn(true).when(accountManagerImpl).isRootAdmin(accountMockId);
        Mockito.doReturn(false).when(accountManagerImpl).isDomainAdmin(accountMockId);

        Mockito.lenient().doNothing().when(accountManagerImpl).validateCurrentPassword(Mockito.eq(userVoMock), Mockito.anyString());

        Mockito.doReturn(accountMock).when(accountManagerImpl).getAccount(Mockito.anyLong());

        Mockito.lenient().doNothing().when(passwordPolicyMock).verifyIfPasswordCompliesWithPasswordPolicies(Mockito.anyString(), Mockito.anyString(), Mockito.anyLong());

        accountManagerImpl.validateUserPasswordAndUpdateIfNeeded("newPassword", userVoMock, null, false);
    }

    @Test
    public void validateUserPasswordAndUpdateIfNeededTestRootAdminUpdatingUserPassword() {
        Mockito.doReturn(accountMock).when(accountManagerImpl).getCurrentCallingAccount();
        Mockito.doReturn(true).when(accountManagerImpl).isRootAdmin(accountMockId);
        Mockito.doReturn(false).when(accountManagerImpl).isDomainAdmin(accountMockId);

        String newPassword = "newPassword";

        String expectedUserPasswordAfterEncoded = configureUserMockAuthenticators(newPassword);

        Mockito.lenient().doNothing().when(accountManagerImpl).validateCurrentPassword(Mockito.eq(userVoMock), Mockito.anyString());

        Mockito.doReturn(accountMock).when(accountManagerImpl).getAccount(Mockito.anyLong());

        Mockito.lenient().doNothing().when(passwordPolicyMock).verifyIfPasswordCompliesWithPasswordPolicies(Mockito.anyString(), Mockito.anyString(), Mockito.anyLong());

        accountManagerImpl.validateUserPasswordAndUpdateIfNeeded(newPassword, userVoMock, null, false);

        Mockito.verify(accountManagerImpl, Mockito.times(0)).validateCurrentPassword(Mockito.eq(userVoMock), Mockito.anyString());
        Mockito.verify(userVoMock, Mockito.times(1)).setPassword(expectedUserPasswordAfterEncoded);
    }

    @Test
    public void validateUserPasswordAndUpdateIfNeededTestDomainAdminUpdatingUserPassword() {
        Mockito.doReturn(accountMock).when(accountManagerImpl).getCurrentCallingAccount();
        Mockito.doReturn(false).when(accountManagerImpl).isRootAdmin(accountMockId);
        Mockito.doReturn(true).when(accountManagerImpl).isDomainAdmin(accountMockId);

        String newPassword = "newPassword";

        String expectedUserPasswordAfterEncoded = configureUserMockAuthenticators(newPassword);

        Mockito.lenient().doNothing().when(accountManagerImpl).validateCurrentPassword(Mockito.eq(userVoMock), Mockito.anyString());

        Mockito.doReturn(accountMock).when(accountManagerImpl).getAccount(Mockito.anyLong());

        Mockito.lenient().doNothing().when(passwordPolicyMock).verifyIfPasswordCompliesWithPasswordPolicies(Mockito.anyString(), Mockito.anyString(), Mockito.anyLong());

        accountManagerImpl.validateUserPasswordAndUpdateIfNeeded(newPassword, userVoMock, null, false);

        Mockito.verify(accountManagerImpl, Mockito.times(0)).validateCurrentPassword(Mockito.eq(userVoMock), Mockito.anyString());
        Mockito.verify(userVoMock, Mockito.times(1)).setPassword(expectedUserPasswordAfterEncoded);
    }

    @Test
    public void validateUserPasswordAndUpdateIfNeededTestUserUpdatingHisPassword() {
        Mockito.doReturn(accountMock).when(accountManagerImpl).getCurrentCallingAccount();
        Mockito.doReturn(false).when(accountManagerImpl).isRootAdmin(accountMockId);
        Mockito.doReturn(false).when(accountManagerImpl).isDomainAdmin(accountMockId);

        String newPassword = "newPassword";
        String expectedUserPasswordAfterEncoded = configureUserMockAuthenticators(newPassword);

        Mockito.doNothing().when(accountManagerImpl).validateCurrentPassword(Mockito.eq(userVoMock), Mockito.anyString());

        String currentPassword = "theCurrentPassword";

        Mockito.doReturn(accountMock).when(accountManagerImpl).getAccount(Mockito.anyLong());

        Mockito.lenient().doNothing().when(passwordPolicyMock).verifyIfPasswordCompliesWithPasswordPolicies(Mockito.anyString(), Mockito.anyString(), Mockito.anyLong());

        accountManagerImpl.validateUserPasswordAndUpdateIfNeeded(newPassword, userVoMock, currentPassword, false);

        Mockito.verify(accountManagerImpl, Mockito.times(1)).validateCurrentPassword(userVoMock, currentPassword);
        Mockito.verify(userVoMock, Mockito.times(1)).setPassword(expectedUserPasswordAfterEncoded);
    }

    @Test (expected = InvalidParameterValueException.class)
    public void validateUserPasswordAndUpdateIfNeededTestIfVerifyIfPasswordCompliesWithPasswordPoliciesThrowsException() {
        String newPassword = "newPassword";

        String currentPassword = "theCurrentPassword";

        Mockito.doReturn(accountMock).when(accountManagerImpl).getAccount(Mockito.anyLong());

        Mockito.doReturn("user").when(userVoMock).getUsername();

        Mockito.doThrow(new InvalidParameterValueException("")).when(passwordPolicyMock).verifyIfPasswordCompliesWithPasswordPolicies(Mockito.anyString(), Mockito.anyString(),
                Mockito.anyLong());

        accountManagerImpl.validateUserPasswordAndUpdateIfNeeded(newPassword, userVoMock, currentPassword, false);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void validateUserPasswordAndUpdateIfNeededTestSaml2UserShouldNotBeAllowedToUpdateTheirPassword() {
        String newPassword = "newPassword";
        String currentPassword = "theCurrentPassword";

        Mockito.when(userVoMock.getSource()).thenReturn(User.Source.SAML2);

        accountManagerImpl.validateUserPasswordAndUpdateIfNeeded(newPassword, userVoMock, currentPassword, false);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void validateUserPasswordAndUpdateIfNeededTestSaml2DisabledUserShouldNotBeAllowedToUpdateTheirPassword() {
        String newPassword = "newPassword";
        String currentPassword = "theCurrentPassword";

        Mockito.when(userVoMock.getSource()).thenReturn(User.Source.SAML2DISABLED);

        accountManagerImpl.validateUserPasswordAndUpdateIfNeeded(newPassword, userVoMock, currentPassword, false);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void validateUserPasswordAndUpdateIfNeededTestLdapUserShouldNotBeAllowedToUpdateTheirPassword() {
        String newPassword = "newPassword";
        String currentPassword = "theCurrentPassword";

        Mockito.when(userVoMock.getSource()).thenReturn(User.Source.LDAP);

        accountManagerImpl.validateUserPasswordAndUpdateIfNeeded(newPassword, userVoMock, currentPassword, false);
    }

    private String configureUserMockAuthenticators(String newPassword) {
        accountManagerImpl._userPasswordEncoders = new ArrayList<>();
        UserAuthenticator authenticatorMock1 = Mockito.mock(UserAuthenticator.class);
        String expectedUserPasswordAfterEncoded = "passwordEncodedByAuthenticator1";
        Mockito.doReturn(expectedUserPasswordAfterEncoded).when(authenticatorMock1).encode(newPassword);

        UserAuthenticator authenticatorMock2 = Mockito.mock(UserAuthenticator.class);
        Mockito.lenient().doReturn("passwordEncodedByAuthenticator2").when(authenticatorMock2).encode(newPassword);

        accountManagerImpl._userPasswordEncoders.add(authenticatorMock1);
        accountManagerImpl._userPasswordEncoders.add(authenticatorMock2);
        return expectedUserPasswordAfterEncoded;
    }

    @Test(expected = InvalidParameterValueException.class)
    public void validateCurrentPasswordTestUserNotAuthenticatedWithProvidedCurrentPassword() {
        Mockito.doReturn(Mockito.mock(AccountVO.class)).when(_accountDao).findById(accountMockId);
        String newPassword = "newPassword";
        configureUserMockAuthenticators(newPassword);

        accountManagerImpl.validateCurrentPassword(userVoMock, "currentPassword");
    }

    @Test
    public void validateCurrentPasswordTestUserAuthenticatedWithProvidedCurrentPasswordViaFirstAuthenticator() {
        AccountVO accountVoMock = Mockito.mock(AccountVO.class);
        long domainId = 14L;
        Mockito.doReturn(domainId).when(accountVoMock).getDomainId();

        Mockito.doReturn(accountVoMock).when(_accountDao).findById(accountMockId);
        String username = "username";
        Mockito.doReturn(username).when(userVoMock).getUsername();

        accountManagerImpl._userPasswordEncoders = new ArrayList<>();
        UserAuthenticator authenticatorMock1 = Mockito.mock(UserAuthenticator.class);
        UserAuthenticator authenticatorMock2 = Mockito.mock(UserAuthenticator.class);

        accountManagerImpl._userPasswordEncoders.add(authenticatorMock1);
        accountManagerImpl._userPasswordEncoders.add(authenticatorMock2);

        Pair<Boolean, ActionOnFailedAuthentication> authenticationResult = new Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication>(true,
                UserAuthenticator.ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT);

        String currentPassword = "currentPassword";
        Mockito.doReturn(authenticationResult).when(authenticatorMock1).authenticate(username, currentPassword, domainId, null);

        accountManagerImpl.validateCurrentPassword(userVoMock, currentPassword);

        Mockito.verify(authenticatorMock1, Mockito.times(1)).authenticate(username, currentPassword, domainId, null);
        Mockito.verify(authenticatorMock2, Mockito.times(0)).authenticate(username, currentPassword, domainId, null);
    }

    @Test
    public void validateCurrentPasswordTestUserAuthenticatedWithProvidedCurrentPasswordViaSecondAuthenticator() {
        AccountVO accountVoMock = Mockito.mock(AccountVO.class);
        long domainId = 14L;
        Mockito.doReturn(domainId).when(accountVoMock).getDomainId();

        Mockito.doReturn(accountVoMock).when(_accountDao).findById(accountMockId);
        String username = "username";
        Mockito.doReturn(username).when(userVoMock).getUsername();

        accountManagerImpl._userPasswordEncoders = new ArrayList<>();
        UserAuthenticator authenticatorMock1 = Mockito.mock(UserAuthenticator.class);
        UserAuthenticator authenticatorMock2 = Mockito.mock(UserAuthenticator.class);

        accountManagerImpl._userPasswordEncoders.add(authenticatorMock1);
        accountManagerImpl._userPasswordEncoders.add(authenticatorMock2);

        Pair<Boolean, ActionOnFailedAuthentication> authenticationResult = new Pair<Boolean, UserAuthenticator.ActionOnFailedAuthentication>(true,
                UserAuthenticator.ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT);

        String currentPassword = "currentPassword";
        Mockito.doReturn(authenticationResult).when(authenticatorMock2).authenticate(username, currentPassword, domainId, null);

        accountManagerImpl.validateCurrentPassword(userVoMock, currentPassword);

        Mockito.verify(authenticatorMock1, Mockito.times(1)).authenticate(username, currentPassword, domainId, null);
        Mockito.verify(authenticatorMock2, Mockito.times(1)).authenticate(username, currentPassword, domainId, null);
    }

    @Test
    public void testUpdateLoginAttemptsDisableMechanism() {
        accountManagerImpl.updateLoginAttemptsWhenIncorrectLoginAttemptsEnabled(userAccountVO, true, 0);
        Mockito.verify(accountManagerImpl, Mockito.never()).updateLoginAttempts(Mockito.anyLong(), Mockito.anyInt(), Mockito.anyBoolean());
    }

    @Test
    public void testUpdateLoginAttemptsEnableMechanismAttemptsLeft() {
        int attempts = 2;
        int allowedAttempts = 5;
        Long accountId = 1L;
        Mockito.when(userAccountVO.getLoginAttempts()).thenReturn(attempts);
        Mockito.when(userAccountVO.getId()).thenReturn(accountId);
        accountManagerImpl.updateLoginAttemptsWhenIncorrectLoginAttemptsEnabled(userAccountVO, true, allowedAttempts);
        Mockito.verify(accountManagerImpl).updateLoginAttempts(Mockito.eq(accountId), Mockito.eq(attempts + 1), Mockito.eq(false));
    }

    @Test
    public void testUpdateLoginAttemptsEnableMechanismNoAttemptsLeft() {
        int attempts = 5;
        int allowedAttempts = 5;
        Long accountId = 1L;
        Mockito.when(userAccountVO.getLoginAttempts()).thenReturn(attempts);
        Mockito.when(userAccountVO.getId()).thenReturn(accountId);
        accountManagerImpl.updateLoginAttemptsWhenIncorrectLoginAttemptsEnabled(userAccountVO, true, allowedAttempts);
        Mockito.verify(accountManagerImpl).updateLoginAttempts(Mockito.eq(accountId), Mockito.eq(allowedAttempts), Mockito.eq(true));
    }

    @Test(expected = CloudRuntimeException.class)
    public void testEnableUserTwoFactorAuthenticationWhenDomainlevelSettingisDisabled() {
        Long userId = 1L;

        UserAccountVO userAccount = Mockito.mock(UserAccountVO.class);
        UserVO userVO = Mockito.mock(UserVO.class);

        Mockito.when(userAccountDao.findById(userId)).thenReturn(userAccount);
        Mockito.when(userDaoMock.findById(userId)).thenReturn(userVO);
        Mockito.when(userAccount.getDomainId()).thenReturn(1L);

        ConfigKey<Boolean> enableUserTwoFactorAuthentication = Mockito.mock(ConfigKey.class);
        AccountManagerImpl.enableUserTwoFactorAuthentication = enableUserTwoFactorAuthentication;

        Mockito.when(enableUserTwoFactorAuthentication.valueIn(1L)).thenReturn(false);

        accountManagerImpl.enableTwoFactorAuthentication(userId, "totp");
    }

    @Test
    public void testEnableUserTwoFactorAuthenticationWhenProviderNameIsNullExpectedDefaultProviderTOTP() {
        Long userId = 1L;

        UserAccountVO userAccount = Mockito.mock(UserAccountVO.class);
        UserVO userVO = Mockito.mock(UserVO.class);

        Mockito.when(userAccountDao.findById(userId)).thenReturn(userAccount);
        Mockito.when(userDaoMock.findById(userId)).thenReturn(userVO);
        Mockito.when(userAccount.getDomainId()).thenReturn(1L);

        ConfigKey<Boolean> enableUserTwoFactorAuthentication = Mockito.mock(ConfigKey.class);
        AccountManagerImpl.enableUserTwoFactorAuthentication = enableUserTwoFactorAuthentication;
        Mockito.when(enableUserTwoFactorAuthentication.valueIn(1L)).thenReturn(true);

        UserTwoFactorAuthenticator totpProvider = Mockito.mock(UserTwoFactorAuthenticator.class);
        Map<String, UserTwoFactorAuthenticator> userTwoFactorAuthenticationProvidersMap = Mockito.mock(HashMap.class);
        Mockito.when(userTwoFactorAuthenticationProvidersMap.containsKey("totp")).thenReturn( true);
        Mockito.when(userTwoFactorAuthenticationProvidersMap.get("totp")).thenReturn(totpProvider);
        AccountManagerImpl.userTwoFactorAuthenticationProvidersMap = userTwoFactorAuthenticationProvidersMap;
        Mockito.when(totpProvider.setup2FAKey(userAccount)).thenReturn("EUJEAEDVOURFZTE6OGWVTJZMI54QGMIL");
        Mockito.when(userDaoMock.createForUpdate()).thenReturn(userVoMock);
        Mockito.when(userDaoMock.update(userId, userVoMock)).thenReturn(true);

        UserTwoFactorAuthenticationSetupResponse response = accountManagerImpl.enableTwoFactorAuthentication(userId, null);

        Assert.assertEquals("EUJEAEDVOURFZTE6OGWVTJZMI54QGMIL", response.getSecretCode());
    }

    @Test
    public void testEnableUserTwoFactorAuthentication() {
        Long userId = 1L;

        UserAccountVO userAccount = Mockito.mock(UserAccountVO.class);
        UserVO userVO = Mockito.mock(UserVO.class);

        Mockito.when(userAccountDao.findById(userId)).thenReturn(userAccount);
        Mockito.when(userDaoMock.findById(userId)).thenReturn(userVO);
        Mockito.when(userAccount.getDomainId()).thenReturn(1L);

        ConfigKey<Boolean> enableUserTwoFactorAuthentication = Mockito.mock(ConfigKey.class);
        AccountManagerImpl.enableUserTwoFactorAuthentication = enableUserTwoFactorAuthentication;
        Mockito.when(enableUserTwoFactorAuthentication.valueIn(1L)).thenReturn(true);

        UserTwoFactorAuthenticator totpProvider = Mockito.mock(UserTwoFactorAuthenticator.class);
        Map<String, UserTwoFactorAuthenticator> userTwoFactorAuthenticationProvidersMap = Mockito.mock(HashMap.class);
        Mockito.when(userTwoFactorAuthenticationProvidersMap.containsKey("totp")).thenReturn( true);
        Mockito.when(userTwoFactorAuthenticationProvidersMap.get("totp")).thenReturn(totpProvider);
        AccountManagerImpl.userTwoFactorAuthenticationProvidersMap = userTwoFactorAuthenticationProvidersMap;
        Mockito.when(totpProvider.setup2FAKey(userAccount)).thenReturn("EUJEAEDVOURFZTE6OGWVTJZMI54QGMIL");
        Mockito.when(userDaoMock.createForUpdate()).thenReturn(userVoMock);
        Mockito.when(userDaoMock.update(userId, userVoMock)).thenReturn(true);

        UserTwoFactorAuthenticationSetupResponse response = accountManagerImpl.enableTwoFactorAuthentication(userId, "totp");

        Assert.assertEquals("EUJEAEDVOURFZTE6OGWVTJZMI54QGMIL", response.getSecretCode());
    }

    @Test
    public void testDisableUserTwoFactorAuthentication() {
        Long userId = 1L;
        Long accountId = 2L;

        UserVO userVO = Mockito.mock(UserVO.class);
        Account caller = Mockito.mock(Account.class);
        Account owner = Mockito.mock(Account.class);

        Mockito.doNothing().when(accountManagerImpl).checkAccess(nullable(Account.class), Mockito.isNull(), nullable(Boolean.class), nullable(Account.class));

        Mockito.when(userDaoMock.findById(userId)).thenReturn(userVO);
        Mockito.when(userVO.getAccountId()).thenReturn(accountId);
        Mockito.when(_accountService.getActiveAccountById(accountId)).thenReturn(owner);

        userVoMock.setKeyFor2fa("EUJEAEDVOURFZTE6OGWVTJZMI54QGMIL");
        userVoMock.setUser2faProvider("totp");
        userVoMock.setUser2faEnabled(true);

        Mockito.when(userDaoMock.createForUpdate()).thenReturn(userVoMock);

        UserTwoFactorAuthenticationSetupResponse response = accountManagerImpl.disableTwoFactorAuthentication(userId, caller, owner);

        Mockito.verify(accountManagerImpl).checkAccess(caller, null, true, owner);
        Assert.assertNull(response.getSecretCode());
        Assert.assertNull(userVoMock.getKeyFor2fa());
        Assert.assertNull(userVoMock.getUser2faProvider());
    }

    @Test(expected = CloudRuntimeException.class)
    public void testVerify2FAcodeWhen2FAisNotEnabled() {
        AccountVO accountMock = Mockito.mock(AccountVO.class);
        Account caller = CallContext.current().getCallingAccount();
        Mockito.when(caller.getId()).thenReturn(1L);
        Mockito.lenient().when(_accountService.getActiveAccountById(1L)).thenReturn(accountMock);
        Mockito.when(_accountService.getUserAccountById(1L)).thenReturn(userAccountVO);
        Mockito.when(userAccountVO.isUser2faEnabled()).thenReturn(false);

        accountManagerImpl.verifyUsingTwoFactorAuthenticationCode("352352", 1L, 1L);
    }

    @Test(expected = CloudRuntimeException.class)
    public void testVerify2FAcodeWhen2FAisNotSetup() {
        AccountVO accountMock = Mockito.mock(AccountVO.class);
        Account caller = CallContext.current().getCallingAccount();
        Mockito.when(caller.getId()).thenReturn(1L);
        Mockito.lenient().when(_accountService.getActiveAccountById(1L)).thenReturn(accountMock);
        Mockito.when(_accountService.getUserAccountById(1L)).thenReturn(userAccountVO);
        Mockito.when(userAccountVO.isUser2faEnabled()).thenReturn(true);
        Mockito.when(userAccountVO.getUser2faProvider()).thenReturn(null);

        accountManagerImpl.verifyUsingTwoFactorAuthenticationCode("352352", 1L, 1L);
    }

    @Test
    public void testVerify2FAcode() {
        AccountVO accountMock = Mockito.mock(AccountVO.class);
        Account caller = CallContext.current().getCallingAccount();
        Mockito.when(caller.getId()).thenReturn(1L);
        Mockito.lenient().when(_accountService.getActiveAccountById(1L)).thenReturn(accountMock);
        Mockito.when(_accountService.getUserAccountById(1L)).thenReturn(userAccountVO);
        Mockito.when(userAccountVO.isUser2faEnabled()).thenReturn(true);
        Mockito.when(userAccountVO.getUser2faProvider()).thenReturn("staticpin");
        Mockito.when(userAccountVO.getKeyFor2fa()).thenReturn("352352");

        UserTwoFactorAuthenticator staticpinProvider = Mockito.mock(UserTwoFactorAuthenticator.class);
        Map<String, UserTwoFactorAuthenticator> userTwoFactorAuthenticationProvidersMap = Mockito.mock(HashMap.class);
        Mockito.when(userTwoFactorAuthenticationProvidersMap.containsKey("staticpin")).thenReturn( true);
        Mockito.when(userTwoFactorAuthenticationProvidersMap.get("staticpin")).thenReturn(staticpinProvider);
        AccountManagerImpl.userTwoFactorAuthenticationProvidersMap = userTwoFactorAuthenticationProvidersMap;

        accountManagerImpl.verifyUsingTwoFactorAuthenticationCode("352352", 1L, 1L);
    }

    @Test
    public void testEnable2FAcode() {
        SetupUserTwoFactorAuthenticationCmd cmd = Mockito.mock(SetupUserTwoFactorAuthenticationCmd.class);
        Mockito.when(cmd.getProvider()).thenReturn("staticpin");

        AccountVO accountMock = Mockito.mock(AccountVO.class);
        Mockito.when(callingAccount.getId()).thenReturn(1L);
        Mockito.when(callingUser.getId()).thenReturn(1L);
        CallContext.register(callingUser, callingAccount); // Calling account is user account i.e normal account
        Mockito.lenient().when(_accountService.getActiveAccountById(1L)).thenReturn(accountMock);
        Mockito.when(userAccountDao.findById(1L)).thenReturn(userAccountVO);
        Mockito.when(userDaoMock.findById(1L)).thenReturn(userVoMock);
        Mockito.when(userAccountVO.getDomainId()).thenReturn(1L);
        Mockito.when(enableUserTwoFactorAuthenticationMock.valueIn(1L)).thenReturn(true);
        Mockito.when(cmd.getEnable()).thenReturn(true);

        UserTwoFactorAuthenticator staticpinProvider = Mockito.mock(UserTwoFactorAuthenticator.class);
        Map<String, UserTwoFactorAuthenticator> userTwoFactorAuthenticationProvidersMap = Mockito.mock(HashMap.class);
        Mockito.when(userTwoFactorAuthenticationProvidersMap.containsKey("staticpin")).thenReturn( true);
        Mockito.when(userTwoFactorAuthenticationProvidersMap.get("staticpin")).thenReturn(staticpinProvider);
        Mockito.when(staticpinProvider.setup2FAKey(userAccountVO)).thenReturn("345543");
        Mockito.when(userDaoMock.createForUpdate()).thenReturn(userVoMock);
        AccountManagerImpl.userTwoFactorAuthenticationProvidersMap = userTwoFactorAuthenticationProvidersMap;

        UserTwoFactorAuthenticationSetupResponse response = accountManagerImpl.setupUserTwoFactorAuthentication(cmd);

        Assert.assertEquals("345543", response.getSecretCode());
    }

    @Test
    public void testGetActiveUserAccountByEmail() {
        String email = "test@example.com";
        Long domainId = 1L;
        List<UserAccountVO> userAccountVOList = new ArrayList<>();
        UserAccountVO userAccountVO = new UserAccountVO();
        userAccountVOList.add(userAccountVO);
        Mockito.when(userAccountDao.getUserAccountByEmail(email, domainId)).thenReturn(userAccountVOList);
        List<UserAccount> userAccounts = accountManagerImpl.getActiveUserAccountByEmail(email, domainId);
        Assert.assertEquals(userAccountVOList.size(), userAccounts.size());
        Assert.assertEquals(userAccountVOList.get(0), userAccounts.get(0));
    }

    @Test
    public void createApiKeyAndSecretKeyTestWithEmptyRules() {
        CallContext.register(callingUser, callingAccount);
        Mockito.lenient().when(callingUser.getId()).thenReturn(111L);
        long userId = 111L;

        Mockito.when(registerCmdMock.getRules()).thenReturn(List.of());
        Mockito.when(registerCmdMock.getUserId()).thenReturn(userId);

        Mockito.when(userDaoMock.findById(any())).thenReturn(userVoMock);
        Mockito.when(_accountDao.findById(Mockito.anyLong())).thenReturn(accountVoMock);
        Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.any(Account.class), Mockito.isNull(), Mockito.anyBoolean(), Mockito.any(Account.class));
        Mockito.doNothing().when(accountManagerImpl).verifyCallerPrivilegeForUserOrAccountOperations(Mockito.any(User.class));
        Mockito.when(apiKeyPairDaoMock.findBySecretKey(Mockito.anyString())).thenReturn(null);
        Mockito.when(roleService.findAllRolePermissionsEntityBy(Mockito.anyLong(), Mockito.anyBoolean())).thenReturn(List.of(
                new RolePermissionVO(1L, "api2", RolePermissionEntity.Permission.ALLOW, "description")
        ));
        Mockito.when(roleService.findRole(Mockito.anyLong())).thenReturn(new RoleVO());
        Mockito.when(roleService.roleHasPermission(Mockito.anyMap(), Mockito.anyList())).thenReturn(true);

        accountManagerImpl.createApiKeyAndSecretKey(registerCmdMock);
        Mockito.verify(apiKeyPairDaoMock, Mockito.times(0)).remove(Mockito.anyLong());
        Mockito.verify(apiKeyPairPermissionsDaoMock, Mockito.times(0)).persist(Mockito.any(ApiKeyPairPermissionVO.class));
    }

    @Test(expected = InvalidParameterValueException.class)
    public void createApiKeyAndSecretKeyTestPermissionNotPresentOnAccount() {
        CallContext.register(callingUser, callingAccount);
        Mockito.lenient().when(callingUser.getId()).thenReturn(111L);
        long userId = 111L;

        List<Map<String, Object>> rules = new ArrayList<>();
        rules.add(Map.of(
                ApiConstants.RULE, "api1",
                ApiConstants.PERMISSION, RolePermission.Permission.ALLOW,
                ApiConstants.DESCRIPTION, "description"
        ));
        Mockito.when(registerCmdMock.getRules()).thenReturn(rules);
        Mockito.when(registerCmdMock.getUserId()).thenReturn(userId);

        ApiKeyPairVO apiKeyPairVO = new ApiKeyPairVO();
        apiKeyPairVO.setUserId(userId);
        apiKeyPairVO.setId(1L);

        Mockito.when(userDaoMock.findById(any())).thenReturn(userVoMock);
        Mockito.when(_accountDao.findById(Mockito.anyLong())).thenReturn(accountVoMock);
        Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.any(Account.class), Mockito.isNull(), Mockito.anyBoolean(), Mockito.any());
        Mockito.doNothing().when(accountManagerImpl).verifyCallerPrivilegeForUserOrAccountOperations(Mockito.any(User.class));
        Mockito.when(roleService.findAllRolePermissionsEntityBy(Mockito.anyLong(), Mockito.anyBoolean())).thenReturn(List.of(
                new RolePermissionVO(1L, "api2", RolePermissionEntity.Permission.ALLOW, "description")
        ));
        Mockito.when(roleService.findRole(Mockito.anyLong())).thenReturn(new RoleVO());

        accountManagerImpl.createApiKeyAndSecretKey(registerCmdMock);
        Mockito.verify(apiKeyPairDaoMock, Mockito.times(1)).remove(Mockito.anyLong());
        Mockito.verify(apiKeyPairPermissionsDaoMock, Mockito.times(0)).persist(Mockito.any(ApiKeyPairPermissionVO.class));
    }

    @Test(expected = InvalidParameterValueException.class)
    public void createApiKeyAndSecretTestKeyDeniedOnAccount() {
        CallContext.register(callingUser, callingAccount);
        Mockito.lenient().when(callingUser.getId()).thenReturn(111L);
        long userId = 111L;

        List<Map<String, Object>> rules = new ArrayList<>();
        rules.add(Map.of(
                ApiConstants.RULE, "api",
                ApiConstants.PERMISSION, RolePermission.Permission.ALLOW,
                ApiConstants.DESCRIPTION, "description"
        ));
        Mockito.when(registerCmdMock.getRules()).thenReturn(rules);
        Mockito.when(registerCmdMock.getUserId()).thenReturn(userId);

        ApiKeyPairVO apiKeyPairVO = new ApiKeyPairVO();
        apiKeyPairVO.setUserId(userId);
        apiKeyPairVO.setId(1L);

        Mockito.when(userDaoMock.findById(Mockito.anyLong())).thenReturn(userVoMock);
        Mockito.when(_accountDao.findById(Mockito.anyLong())).thenReturn(accountVoMock);
        Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.any(Account.class), Mockito.isNull(), Mockito.anyBoolean(), Mockito.any());
        Mockito.doNothing().when(accountManagerImpl).verifyCallerPrivilegeForUserOrAccountOperations(Mockito.any(User.class));
        Mockito.when(apiKeyPairDaoMock.findBySecretKey(Mockito.anyString())).thenReturn(null);
        Mockito.when(roleService.findAllRolePermissionsEntityBy(Mockito.anyLong(), Mockito.anyBoolean())).thenReturn(List.of(
                new RolePermissionVO(1L, "api", RolePermissionEntity.Permission.DENY, "description")
        ));
        Mockito.when(roleService.findRole(Mockito.anyLong())).thenReturn(new RoleVO());

        accountManagerImpl.createApiKeyAndSecretKey(registerCmdMock);
        Mockito.verify(apiKeyPairDaoMock, Mockito.times(1)).remove(Mockito.anyLong());
        Mockito.verify(apiKeyPairPermissionsDaoMock, Mockito.times(0)).persist(Mockito.any(ApiKeyPairPermissionVO.class));
    }

    @Test
    public void createApiKeyAndSecretKeyTestAllowedOnAccount() {
        CallContext.register(callingUser, callingAccount);
        Mockito.lenient().when(callingUser.getId()).thenReturn(111L);
        long userId = callingUser.getId();

        List<Map<String, Object>> rules = new ArrayList<>();
        rules.add(Map.of(
                ApiConstants.RULE, "api",
                ApiConstants.PERMISSION, RolePermission.Permission.ALLOW,
                ApiConstants.DESCRIPTION, "description"
        ));
        Mockito.when(registerCmdMock.getRules()).thenReturn(rules);
        Mockito.when(registerCmdMock.getUserId()).thenReturn(userId);

        ApiKeyPairPermissionVO permissionVO = new ApiKeyPairPermissionVO();
        ApiKeyPairVO apiKeyPairVO = new ApiKeyPairVO();
        apiKeyPairVO.setUserId(userId);
        apiKeyPairVO.setId(1L);

        Mockito.when(userDaoMock.findById(Mockito.anyLong())).thenReturn(userVoMock);
        Mockito.when(_accountDao.findById(Mockito.anyLong())).thenReturn(accountVoMock);
        Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.any(Account.class), Mockito.isNull(), Mockito.anyBoolean(), Mockito.any(Account.class));
        Mockito.doNothing().when(accountManagerImpl).verifyCallerPrivilegeForUserOrAccountOperations(Mockito.any(User.class));
        Mockito.when(apiKeyPairPermissionsDaoMock.persist(Mockito.any(ApiKeyPairPermissionVO.class))).thenReturn(permissionVO);
        Mockito.doReturn(true).when(roleService).roleHasPermission(Mockito.any(), Mockito.any());
        Mockito.when(roleService.findRole(Mockito.anyLong())).thenReturn(new RoleVO());

        Assert.assertEquals((long) accountManagerImpl.createApiKeyAndSecretKey(registerCmdMock).getUserId(), userId);
        Mockito.verify(apiKeyPairPermissionsDaoMock, Mockito.times(1)).persist(Mockito.any(ApiKeyPairPermissionVO.class));
    }


    @Test
    public void createApiAndSecretKeyTestWithNonEmptyDates() {
        CallContext.register(callingUser, callingAccount);
        Mockito.lenient().when(callingUser.getId()).thenReturn(111L);
        Date startDate = Date.from(Instant.parse("2024-03-03T10:15:30.00Z"));
        Date endDate = Date.from(Instant.parse("2124-03-04T10:15:30.00Z"));
        long userId = 111L;

        List<Map<String, Object>> rules = new ArrayList<>();
        rules.add(Map.of(
                ApiConstants.RULE, "api",
                ApiConstants.PERMISSION, RolePermission.Permission.ALLOW,
                ApiConstants.DESCRIPTION, "description"
        ));
        Mockito.when(registerCmdMock.getRules()).thenReturn(rules);
        Mockito.when(registerCmdMock.getUserId()).thenReturn(userId);
        Mockito.when(registerCmdMock.getStartDate()).thenReturn(startDate);
        Mockito.when(registerCmdMock.getEndDate()).thenReturn(endDate);
        Mockito.when(registerCmdMock.getDescription()).thenReturn("key description");

        UserVO mockUser = new UserVO(userId);
        ApiKeyPairPermissionVO permissionVO = new ApiKeyPairPermissionVO();
        ApiKeyPairVO apiKeyPairVO = new ApiKeyPairVO();
        apiKeyPairVO.setUserId(userId);
        apiKeyPairVO.setId(1L);

        Mockito.when(userDaoMock.findById(Mockito.anyLong())).thenReturn(userVoMock);
        Mockito.when(_accountDao.findById(Mockito.anyLong())).thenReturn(accountVoMock);
        Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.any(Account.class), Mockito.isNull(), Mockito.anyBoolean(), Mockito.any(Account.class));
        Mockito.doNothing().when(accountManagerImpl).verifyCallerPrivilegeForUserOrAccountOperations(Mockito.any(User.class));
        Mockito.when(apiKeyPairPermissionsDaoMock.persist(Mockito.any(ApiKeyPairPermissionVO.class))).thenReturn(permissionVO);
        Mockito.when(apiKeyPairDaoMock.findBySecretKey(Mockito.anyString())).thenReturn(null);
        Mockito.doReturn(true).when(roleService).roleHasPermission(Mockito.any(), Mockito.any());
        Mockito.when(roleService.findRole(Mockito.anyLong())).thenReturn(new RoleVO());

        ApiKeyPair response = accountManagerImpl.createApiKeyAndSecretKey(registerCmdMock);
        Mockito.verify(apiKeyPairDaoMock, Mockito.times(1)).persist(Mockito.any(ApiKeyPairVO.class));
        Assert.assertEquals(userId, (long) response.getUserId());
        Assert.assertEquals(response.getStartDate(), startDate);
        Assert.assertEquals(response.getEndDate(), endDate);
        Assert.assertEquals("key description", response.getDescription());
    }

    @Test(expected = InvalidParameterValueException.class)
    public void createApiAndSecretKeyTestWithExpiredDate() {
        CallContext.register(callingUser, callingAccount);
        Mockito.lenient().when(callingUser.getId()).thenReturn(111L);

        Date startDate = Date.from(Instant.parse("2024-03-01T10:15:30.00Z"));
        Date endDate = Date.from(Instant.parse("2024-03-02T10:15:30.00Z"));
        long userId = 111L;

        List<Map<String, Object>> rules = new ArrayList<>();
        rules.add(Map.of(
                ApiConstants.RULE, "api",
                ApiConstants.PERMISSION, RolePermission.Permission.ALLOW,
                ApiConstants.DESCRIPTION, "description"
        ));
        Mockito.when(registerCmdMock.getRules()).thenReturn(rules);
        Mockito.when(registerCmdMock.getUserId()).thenReturn(userId);
        Mockito.when(registerCmdMock.getStartDate()).thenReturn(startDate);
        Mockito.when(registerCmdMock.getEndDate()).thenReturn(endDate);
        Mockito.when(registerCmdMock.getDescription()).thenReturn("key description");

        UserVO mockUser = new UserVO(userId);
        ApiKeyPairPermissionVO permissionVO = new ApiKeyPairPermissionVO();
        ApiKeyPairVO apiKeyPairVO = new ApiKeyPairVO();
        apiKeyPairVO.setUserId(userId);
        apiKeyPairVO.setId(1L);

        Mockito.when(userDaoMock.findById(Mockito.anyLong())).thenReturn(userVoMock);
        Mockito.when(_accountDao.findById(Mockito.anyLong())).thenReturn(accountVoMock);
        Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.any(Account.class), Mockito.isNull(), Mockito.anyBoolean(), Mockito.any(Account.class));
        Mockito.doNothing().when(accountManagerImpl).verifyCallerPrivilegeForUserOrAccountOperations(Mockito.any(User.class));

        ApiKeyPair response = accountManagerImpl.createApiKeyAndSecretKey(registerCmdMock);
        Assert.assertEquals((long) response.getUserId(), userId);
        Assert.assertEquals(response.getStartDate(), startDate);
        Assert.assertEquals(response.getEndDate(), endDate);
        Assert.assertEquals(response.getDescription(), "key description");
    }

    @Test(expected = InvalidParameterValueException.class)
    public void createApiAndSecretKeyTestWithInvalidDate() {
        CallContext.register(callingUser, callingAccount);
        Mockito.lenient().when(callingUser.getId()).thenReturn(111L);

        Date endDate = Date.from(Instant.parse("2024-03-02T10:15:30.00Z")); // this test will break in 100 years :O
        Date startDate = Date.from(Instant.parse("2024-10-02T10:15:30.00Z"));
        long userId = 111L;

        List<Map<String, Object>> rules = new ArrayList<>();
        rules.add(Map.of(
                ApiConstants.RULE, "api",
                ApiConstants.PERMISSION, RolePermission.Permission.ALLOW,
                ApiConstants.DESCRIPTION, "description"
        ));
        Mockito.when(registerCmdMock.getRules()).thenReturn(rules);
        Mockito.when(registerCmdMock.getUserId()).thenReturn(userId);
        Mockito.when(registerCmdMock.getStartDate()).thenReturn(startDate);
        Mockito.when(registerCmdMock.getEndDate()).thenReturn(endDate);
        Mockito.when(registerCmdMock.getDescription()).thenReturn("key description");

        UserVO mockUser = new UserVO(userId);
        ApiKeyPairPermissionVO permissionVO = new ApiKeyPairPermissionVO();
        ApiKeyPairVO apiKeyPairVO = new ApiKeyPairVO();
        apiKeyPairVO.setUserId(userId);
        apiKeyPairVO.setId(1L);

        Mockito.when(userDaoMock.findById(Mockito.anyLong())).thenReturn(userVoMock);
        Mockito.when(_accountDao.findById(Mockito.anyLong())).thenReturn(accountVoMock);
        Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.any(Account.class), Mockito.isNull(), Mockito.anyBoolean(), Mockito.any(Account.class));
        Mockito.doNothing().when(accountManagerImpl).verifyCallerPrivilegeForUserOrAccountOperations(Mockito.any(User.class));

        ApiKeyPair response = accountManagerImpl.createApiKeyAndSecretKey(registerCmdMock);
        Assert.assertEquals(userId, (long) response.getUserId());
        Assert.assertEquals(response.getStartDate(), startDate);
        Assert.assertEquals(response.getEndDate(), endDate);
        Assert.assertEquals("key description", response.getDescription());
    }

    @Test(expected = InvalidParameterValueException.class)
    public void createApiAndSecretKeyTestWithMultipleAllowedPermissionsOneDenied() {
        CallContext.register(callingUser, callingAccount);
        Mockito.lenient().when(callingUser.getId()).thenReturn(111L);
        long userId = 111L;

        List<Map<String, Object>> rules = new ArrayList<>();
        rules.add(Map.of(
                ApiConstants.RULE, "api1",
                ApiConstants.PERMISSION, RolePermission.Permission.ALLOW,
                ApiConstants.DESCRIPTION, "description"
        ));
        rules.add(Map.of(
                ApiConstants.RULE, "api2",
                ApiConstants.PERMISSION, RolePermission.Permission.ALLOW,
                ApiConstants.DESCRIPTION, "description"
        ));
        rules.add(Map.of(
                ApiConstants.RULE, "api3",
                ApiConstants.PERMISSION, RolePermission.Permission.ALLOW,
                ApiConstants.DESCRIPTION, "description"
        ));
        Mockito.when(registerCmdMock.getRules()).thenReturn(rules);
        Mockito.when(registerCmdMock.getUserId()).thenReturn(userId);

        UserVO mockUser = new UserVO(userId);
        ApiKeyPairVO apiKeyPairVO = new ApiKeyPairVO();
        apiKeyPairVO.setUserId(userId);
        apiKeyPairVO.setId(1L);

        Mockito.when(userDaoMock.findById(Mockito.anyLong())).thenReturn(userVoMock);
        Mockito.when(_accountDao.findById(Mockito.anyLong())).thenReturn(accountVoMock);
        Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.any(Account.class), Mockito.isNull(), Mockito.anyBoolean(), Mockito.any(Account.class));
        Mockito.doNothing().when(accountManagerImpl).verifyCallerPrivilegeForUserOrAccountOperations(Mockito.any(User.class));
        Mockito.when(apiKeyPairDaoMock.findBySecretKey(Mockito.anyString())).thenReturn(null);
        Mockito.when(roleService.findAllRolePermissionsEntityBy(Mockito.anyLong(), Mockito.anyBoolean())).thenReturn(List.of(
                new RolePermissionVO(1L, "api1", RolePermissionEntity.Permission.ALLOW, "description-1"),
                new RolePermissionVO(1L, "api2", RolePermissionEntity.Permission.ALLOW, "description-2"),
                new RolePermissionVO(1L, "api3", RolePermissionEntity.Permission.DENY, "description-3")
        ));
        Mockito.when(roleService.findRole(Mockito.anyLong())).thenReturn(new RoleVO());

        accountManagerImpl.createApiKeyAndSecretKey(registerCmdMock);
        Mockito.verify(apiKeyPairDaoMock, Mockito.times(1)).remove(Mockito.anyLong());
        Mockito.verify(apiKeyPairPermissionsDaoMock, Mockito.times(0)).persist(Mockito.any(ApiKeyPairPermissionVO.class));
    }

    @Test(expected = InvalidParameterValueException.class)
    public void createApiAndSecretKeyTestWithMultipleAllowedPermissionsOneDoesNotExist() {
        CallContext.register(callingUser, callingAccount);
        Mockito.lenient().when(callingUser.getId()).thenReturn(111L);
        long userId = 111L;

        List<Map<String, Object>> rules = new ArrayList<>();
        rules.add(Map.of(
                ApiConstants.RULE, "api1",
                ApiConstants.PERMISSION, RolePermission.Permission.ALLOW,
                ApiConstants.DESCRIPTION, "description"
        ));
        rules.add(Map.of(
                ApiConstants.RULE, "api2",
                ApiConstants.PERMISSION, RolePermission.Permission.ALLOW,
                ApiConstants.DESCRIPTION, "description"
        ));
        rules.add(Map.of(
                ApiConstants.RULE, "api3",
                ApiConstants.PERMISSION, RolePermission.Permission.DENY,
                ApiConstants.DESCRIPTION, "description"
        ));
        Mockito.when(registerCmdMock.getRules()).thenReturn(rules);
        Mockito.when(registerCmdMock.getUserId()).thenReturn(userId);

        ApiKeyPairVO apiKeyPairVO = new ApiKeyPairVO();
        apiKeyPairVO.setUserId(userId);
        apiKeyPairVO.setId(1L);

        Mockito.when(userDaoMock.findById(Mockito.anyLong())).thenReturn(userVoMock);
        Mockito.when(_accountDao.findById(Mockito.anyLong())).thenReturn(accountVoMock);
        Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.any(Account.class), Mockito.isNull(), Mockito.anyBoolean(), Mockito.any(Account.class));
        Mockito.doNothing().when(accountManagerImpl).verifyCallerPrivilegeForUserOrAccountOperations(Mockito.any(User.class));
        Mockito.when(apiKeyPairDaoMock.findBySecretKey(Mockito.anyString())).thenReturn(null);
        Mockito.when(roleService.findAllRolePermissionsEntityBy(Mockito.anyLong(), Mockito.anyBoolean())).thenReturn(List.of(
                new RolePermissionVO(1L, "api1", RolePermissionEntity.Permission.ALLOW, "description-1"),
                new RolePermissionVO(1L, "api2", RolePermissionEntity.Permission.ALLOW, "description-2")
        ));
        Mockito.when(roleService.findRole(Mockito.anyLong())).thenReturn(new RoleVO());

        accountManagerImpl.createApiKeyAndSecretKey(registerCmdMock);
        Mockito.verify(apiKeyPairDaoMock, Mockito.times(0)).remove(Mockito.anyLong());
        Mockito.verify(apiKeyPairPermissionsDaoMock, Mockito.times(0)).persist(Mockito.any(ApiKeyPairPermissionVO.class));
    }

    @Test
    public void validateAccountHasAccessToResourceTestValidatesAccessToControlledEntity() {
        VMInstanceVO vmInstanceVo = new VMInstanceVO();
        Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.any(), Mockito.any(), Mockito.anyBoolean(), Mockito.any());

        accountManagerImpl.validateAccountHasAccessToResource(callingAccount, AccessType.UseEntry, vmInstanceVo);

        Mockito.verify(accountManagerImpl).checkAccess(callingAccount, AccessType.UseEntry, true, vmInstanceVo);
    }

    @Test
    public void testDeleteWebhooksForAccount() {
        try (MockedStatic<ComponentContext> mockedComponentContext = Mockito.mockStatic(ComponentContext.class)) {
            WebhookHelper webhookHelper = Mockito.mock(WebhookHelper.class);
            Mockito.doNothing().when(webhookHelper).deleteWebhooksForAccount(Mockito.anyLong());
            mockedComponentContext.when(() -> ComponentContext.getDelegateComponentOfType(WebhookHelper.class))
                    .thenReturn(webhookHelper);
            accountManagerImpl.deleteWebhooksForAccount(1L);
        }
    }

    @Test
    public void testDeleteWebhooksForAccountNoBean() {
        try (MockedStatic<ComponentContext> mockedComponentContext = Mockito.mockStatic(ComponentContext.class)) {
            mockedComponentContext.when(() -> ComponentContext.getDelegateComponentOfType(WebhookHelper.class))
                    .thenThrow(NoSuchBeanDefinitionException.class);
            accountManagerImpl.deleteWebhooksForAccount(1L);
        }
    }

    @Test(expected = PermissionDeniedException.class)
    public void testValidateRoleChangeUnknownCaller() {
        Account account = Mockito.mock(Account.class);
        Mockito.when(account.getRoleId()).thenReturn(1L);
        Role role = Mockito.mock(Role.class);
        Mockito.when(role.getRoleType()).thenReturn(RoleType.Unknown);
        Account caller = Mockito.mock(Account.class);
        Mockito.when(caller.getRoleId()).thenReturn(2L);
        Mockito.when(roleService.findRole(2L)).thenReturn(role);
        accountManagerImpl.validateRoleChange(account, Mockito.mock(Role.class), caller);
    }

    @Test(expected = PermissionDeniedException.class)
    public void testValidateRoleChangeUnknownNewRole() {
        Account account = Mockito.mock(Account.class);
        Mockito.when(account.getRoleId()).thenReturn(1L);
        Role newRole = Mockito.mock(Role.class);
        Mockito.when(newRole.getRoleType()).thenReturn(RoleType.Unknown);
        Role callerRole = Mockito.mock(Role.class);
        Mockito.when(callerRole.getRoleType()).thenReturn(RoleType.DomainAdmin);
        Account caller = Mockito.mock(Account.class);
        Mockito.when(caller.getRoleId()).thenReturn(2L);
        Mockito.when(roleService.findRole(2L)).thenReturn(callerRole);
        accountManagerImpl.validateRoleChange(account, newRole, caller);
    }

    @Test
    public void testValidateRoleNewRoleSameCaller() {
        Account account = Mockito.mock(Account.class);
        Mockito.when(account.getRoleId()).thenReturn(1L);
        Role currentRole = Mockito.mock(Role.class);
        Mockito.when(currentRole.getRoleType()).thenReturn(RoleType.User);
        Mockito.when(roleService.findRole(1L)).thenReturn(currentRole);
        Role newRole = Mockito.mock(Role.class);
        Mockito.when(newRole.getRoleType()).thenReturn(RoleType.DomainAdmin);
        Role callerRole = Mockito.mock(Role.class);
        Mockito.when(callerRole.getRoleType()).thenReturn(RoleType.DomainAdmin);
        Account caller = Mockito.mock(Account.class);
        Mockito.when(caller.getRoleId()).thenReturn(2L);
        Mockito.when(roleService.findRole(2L)).thenReturn(callerRole);
        accountManagerImpl.validateRoleChange(account, newRole, caller);
    }

    @Test
    public void testValidateRoleCurrentRoleSameCaller() {
        Account account = Mockito.mock(Account.class);
        Mockito.when(account.getRoleId()).thenReturn(1L);
        Role accountRole = Mockito.mock(Role.class);
        Mockito.when(accountRole.getRoleType()).thenReturn(RoleType.DomainAdmin);
        Role newRole = Mockito.mock(Role.class);
        Mockito.when(newRole.getRoleType()).thenReturn(RoleType.User);
        Role callerRole = Mockito.mock(Role.class);
        Mockito.when(callerRole.getRoleType()).thenReturn(RoleType.DomainAdmin);
        Account caller = Mockito.mock(Account.class);
        Mockito.when(caller.getRoleId()).thenReturn(2L);
        Mockito.when(roleService.findRole(1L)).thenReturn(accountRole);
        Mockito.when(roleService.findRole(2L)).thenReturn(callerRole);
        accountManagerImpl.validateRoleChange(account, newRole, caller);
    }

    @Test(expected = PermissionDeniedException.class)
    public void testValidateRoleNewRoleHigherCaller() {
        Account account = Mockito.mock(Account.class);
        Mockito.when(account.getRoleId()).thenReturn(1L);
        Role newRole = Mockito.mock(Role.class);
        Mockito.when(newRole.getRoleType()).thenReturn(RoleType.Admin);
        Role callerRole = Mockito.mock(Role.class);
        Mockito.when(callerRole.getRoleType()).thenReturn(RoleType.DomainAdmin);
        Account caller = Mockito.mock(Account.class);
        Mockito.when(caller.getRoleId()).thenReturn(2L);
        Mockito.when(roleService.findRole(2L)).thenReturn(callerRole);
        accountManagerImpl.validateRoleChange(account, newRole, caller);
    }

    @Test
    public void testValidateRoleNewRoleLowerCaller() {
        Account account = Mockito.mock(Account.class);
        Mockito.when(account.getRoleId()).thenReturn(1L);
        Role newRole = Mockito.mock(Role.class);
        Mockito.when(newRole.getRoleType()).thenReturn(RoleType.User);
        Role accountRole = Mockito.mock(Role.class);
        Mockito.when(accountRole.getRoleType()).thenReturn(RoleType.User);
        Role callerRole = Mockito.mock(Role.class);
        Mockito.when(callerRole.getRoleType()).thenReturn(RoleType.DomainAdmin);
        Account caller = Mockito.mock(Account.class);
        Mockito.when(caller.getRoleId()).thenReturn(2L);
        Mockito.when(roleService.findRole(1L)).thenReturn(accountRole);
        Mockito.when(roleService.findRole(2L)).thenReturn(callerRole);
        accountManagerImpl.validateRoleChange(account, newRole, caller);
    }

    @Test(expected = PermissionDeniedException.class)
    public void testValidateRoleAdminCannotEscalateAdminFromNonRootDomain() {
        Account account = Mockito.mock(Account.class);
        Mockito.when(account.getRoleId()).thenReturn(1L);
        Mockito.when(account.getDomainId()).thenReturn(2L);
        Role newRole = Mockito.mock(Role.class);
        Mockito.when(newRole.getRoleType()).thenReturn(RoleType.Admin);
        Role accountRole = Mockito.mock(Role.class);
        Role callerRole = Mockito.mock(Role.class);
        Mockito.when(callerRole.getRoleType()).thenReturn(RoleType.Admin);
        Account caller = Mockito.mock(Account.class);
        Mockito.when(caller.getRoleId()).thenReturn(2L);
        Mockito.when(roleService.findRole(1L)).thenReturn(accountRole);
        Mockito.when(roleService.findRole(2L)).thenReturn(callerRole);
        accountManagerImpl.validateRoleChange(account, newRole, caller);
    }

    @Test(expected = PermissionDeniedException.class)
    public void testValidateRoleAdminCannotChangeDefaultAdmin() {
        Account account = Mockito.mock(Account.class);
        Mockito.when(account.isDefault()).thenReturn(true);
        Mockito.when(account.getRoleId()).thenReturn(1L);
        Role newRole = Mockito.mock(Role.class);
        Mockito.when(newRole.getRoleType()).thenReturn(RoleType.User);
        Role callerRole = Mockito.mock(Role.class);
        Mockito.when(callerRole.getRoleType()).thenReturn(RoleType.Admin);
        Account caller = Mockito.mock(Account.class);
        Mockito.when(caller.getRoleId()).thenReturn(2L);
        Mockito.when(roleService.findRole(1L)).thenReturn(Mockito.mock(Role.class));
        Mockito.when(roleService.findRole(2L)).thenReturn(callerRole);
        accountManagerImpl.validateRoleChange(account, newRole, caller);
    }

    @Test
    public void checkIfAccountManagesProjectsTestNotThrowExceptionWhenTheAccountIsNotAProjectAdministrator() {
        long accountId = 1L;
        List<Long> managedProjectIds = new ArrayList<>();

        Mockito.when(_projectAccountDao.listAdministratedProjectIds(accountId)).thenReturn(managedProjectIds);
        accountManagerImpl.checkIfAccountManagesProjects(accountId);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void checkIfAccountManagesProjectsTestThrowExceptionWhenTheAccountIsAProjectAdministrator() {
        long accountId = 1L;
        List<Long> managedProjectIds = List.of(1L);

        Mockito.when(_projectAccountDao.listAdministratedProjectIds(accountId)).thenReturn(managedProjectIds);
        accountManagerImpl.checkIfAccountManagesProjects(accountId);
    }

    @Test
    public void testClearUser2FA_When2FADisabled_NoChanges() {
        UserAccount user = Mockito.mock(UserAccount.class);
        Mockito.when(user.isUser2faEnabled()).thenReturn(false);
        Mockito.when(user.getUser2faProvider()).thenReturn(null);
        UserAccount result = accountManagerImpl.clearUserTwoFactorAuthenticationInSetupStateOnLogin(user);
        Assert.assertSame(user, result);
        Mockito.verifyNoInteractions(userDetailsDaoMock, userAccountDao);
    }

    @Test
    public void testClearUser2FA_When2FAInVerifiedState_NoChanges() {
        UserAccount user = Mockito.mock(UserAccount.class);
        Mockito.when(user.getId()).thenReturn(1L);
        Mockito.when(user.isUser2faEnabled()).thenReturn(true);
        UserDetailVO userDetail = new UserDetailVO();
        userDetail.setValue(UserAccountVO.Setup2FAstatus.VERIFIED.name());
        Mockito.when(userDetailsDaoMock.findDetail(1L, UserDetailVO.Setup2FADetail)).thenReturn(userDetail);
        UserAccount result = accountManagerImpl.clearUserTwoFactorAuthenticationInSetupStateOnLogin(user);
        Assert.assertSame(user, result);
        Mockito.verify(userDetailsDaoMock).findDetail(1L, UserDetailVO.Setup2FADetail);
        Mockito.verifyNoMoreInteractions(userDetailsDaoMock, userAccountDao);
    }

    @Test
    public void testClearUser2FA_When2FAInSetupState_Disable2FA() {
        UserAccount user = Mockito.mock(UserAccount.class);
        Mockito.when(user.getId()).thenReturn(1L);
        Mockito.when(user.isUser2faEnabled()).thenReturn(true);
        UserDetailVO userDetail = new UserDetailVO();
        userDetail.setValue(UserAccountVO.Setup2FAstatus.ENABLED.name());
        UserAccountVO userAccountVO = new UserAccountVO();
        userAccountVO.setId(1L);
        Mockito.when(userDetailsDaoMock.findDetail(1L, UserDetailVO.Setup2FADetail)).thenReturn(userDetail);
        Mockito.when(userAccountDao.findById(any())).thenReturn(userAccountVO);
        UserAccount result = accountManagerImpl.clearUserTwoFactorAuthenticationInSetupStateOnLogin(user);
        Assert.assertNotNull(result);
        Assert.assertFalse(result.isUser2faEnabled());
        Assert.assertNull(result.getUser2faProvider());
        Mockito.verify(userDetailsDaoMock).findDetail(1L, UserDetailVO.Setup2FADetail);
        Mockito.verify(userDetailsDaoMock).remove(Mockito.anyLong());
        Mockito.verify(userAccountDao).findById(1L);
        ArgumentCaptor<UserAccountVO> captor = ArgumentCaptor.forClass(UserAccountVO.class);
        Mockito.verify(userAccountDao).update(Mockito.eq(1L), captor.capture());
        UserAccountVO updatedUser = captor.getValue();
        Assert.assertFalse(updatedUser.isUser2faEnabled());
        Assert.assertNull(updatedUser.getUser2faProvider());
        Assert.assertNull(updatedUser.getKeyFor2fa());
    }

    @Test(expected = InvalidParameterValueException.class)
    public void testAssertUserNotAlreadyInAccount_UserExistsInAccount() {
        User existingUser = new UserVO();
        existingUser.setUsername("testuser");
        existingUser.setAccountId(1L);

        Account newAccount = Mockito.mock(Account.class);
        Mockito.when(newAccount.getId()).thenReturn(1L);

        AccountVO existingAccount = Mockito.mock(AccountVO.class);
        Mockito.when(existingAccount.getUuid()).thenReturn("existing-account-uuid");
        Mockito.when(existingAccount.getAccountName()).thenReturn("existing-account");

        Mockito.when(_accountDao.findById(1L)).thenReturn(existingAccount);

        accountManagerImpl.assertUserNotAlreadyInAccount(existingUser, newAccount);
    }

    @Test
    public void testAssertUserNotAlreadyInAccount_UserExistsInDiffAccount() {
        User existingUser = new UserVO();
        existingUser.setUsername("testuser");
        existingUser.setAccountId(2L);

        Account newAccount = Mockito.mock(Account.class);
        Mockito.when(newAccount.getId()).thenReturn(1L);

        accountManagerImpl.assertUserNotAlreadyInAccount(existingUser, newAccount);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void testAssertUserNotAlreadyInDomain_UserExistsInDomain() {
        User existingUser = new UserVO();
        existingUser.setUsername("testuser");
        existingUser.setAccountId(1L);

        Account originalAccount = Mockito.mock(Account.class);
        Mockito.when(originalAccount.getDomainId()).thenReturn(1L);

        AccountVO existingAccount = Mockito.mock(AccountVO.class);
        Mockito.when(existingAccount.getDomainId()).thenReturn(1L);
        Mockito.when(existingAccount.getUuid()).thenReturn("existing-account-uuid");
        Mockito.when(existingAccount.getAccountName()).thenReturn("existing-account");

        DomainVO existingDomain = Mockito.mock(DomainVO.class);
        Mockito.when(existingDomain.getUuid()).thenReturn("existing-domain-uuid");
        Mockito.when(existingDomain.getName()).thenReturn("existing-domain");

        Mockito.when(_accountDao.findById(1L)).thenReturn(existingAccount);
        Mockito.when(_domainDao.findById(1L)).thenReturn(existingDomain);

        accountManagerImpl.assertUserNotAlreadyInDomain(existingUser, originalAccount);
    }

    @Test
    public void testAssertUserNotAlreadyInDomain_UserExistsInDiffDomain() {
        User existingUser = new UserVO();
        existingUser.setUsername("testuser");
        existingUser.setAccountId(1L);

        Account originalAccount = Mockito.mock(Account.class);
        Mockito.when(originalAccount.getDomainId()).thenReturn(1L);

        AccountVO existingAccount = Mockito.mock(AccountVO.class);
        Mockito.when(existingAccount.getDomainId()).thenReturn(2L);

        Mockito.when(_accountDao.findById(1L)).thenReturn(existingAccount);

        accountManagerImpl.assertUserNotAlreadyInDomain(existingUser, originalAccount);
    }

    @Test
    public void deleteApiKeyTestOnePermission() {
        Mockito.when(apiKeyPairPermissionsDaoMock.findAllByApiKeyPairId(Mockito.any())).thenReturn(List.of(new ApiKeyPairPermissionVO()));
        Mockito.when(userDaoMock.findByIdIncludingRemoved(Mockito.any())).thenReturn(new UserVO());
        accountManagerImpl.deleteApiKey(new ApiKeyPairVO(1L, 1L));
        Mockito.verify(apiKeyPairPermissionsDaoMock, Mockito.times(1)).remove(Mockito.anyLong());
        Mockito.verify(apiKeyPairDaoMock, Mockito.times(1)).remove(Mockito.anyLong());
    }

    @Test
    public void testCheckCallerRoleTypeAllowedToUpdateUserSameAccount() {
        Mockito.lenient().when(accountManagerImpl.getCurrentCallingAccount()).thenReturn(accountMock);
        Mockito.lenient().when(accountManagerImpl.getRoleType(Mockito.eq(accountMock))).thenReturn(RoleType.DomainAdmin);

        accountManagerImpl.checkCallerRoleTypeAllowedForUserOrAccountOperations(accountMock, userVoMock);
    }

    @Test(expected = PermissionDeniedException.class)
    public void testCheckCallerRoleTypeAllowedToUpdateUserLowerAccountRoleType() {
        Account callingAccount = Mockito.mock(Account.class);
        Mockito.lenient().when(callingAccount.getAccountId()).thenReturn(2L);
        Mockito.lenient().doReturn(callingAccount).when(accountManagerImpl).getAccount(2L);
        Mockito.lenient().when(accountManagerImpl.getCurrentCallingAccount()).thenReturn(callingAccount);
        Mockito.lenient().when(accountManagerImpl.getRoleType(Mockito.eq(callingAccount))).thenReturn(RoleType.DomainAdmin);
        Mockito.lenient().when(accountManagerImpl.getRoleType(Mockito.eq(accountMock))).thenReturn(RoleType.Admin);
        accountManagerImpl.checkCallerRoleTypeAllowedForUserOrAccountOperations(accountMock, userVoMock);
    }

    @Test
    public void testcheckCallerApiPermissionsForUserOperationsRootAdminSameCaller() {
        Mockito.lenient().when(accountManagerImpl.getCurrentCallingAccount()).thenReturn(accountMock);
        Mockito.when(accountMock.getId()).thenReturn(2L);
        Mockito.doReturn(true).when(accountManagerImpl).isRootAdmin(2L);
        accountManagerImpl.checkCallerApiPermissionsForUserOrAccountOperations(accountMock);
    }

    @Test(expected = PermissionDeniedException.class)
    public void testcheckCallerApiPermissionsForUserOperationsRootAdminDifferentAccount() {
        Mockito.lenient().when(accountManagerImpl.getCurrentCallingAccount()).thenReturn(callingAccount);
        Mockito.lenient().when(callingAccount.getAccountId()).thenReturn(3L);
        Mockito.lenient().doReturn(callingAccount).when(accountManagerImpl).getAccount(3L);
        Mockito.lenient().doReturn(false).when(accountManagerImpl).isRootAdmin(3L);

        Mockito.when(accountMock.getAccountId()).thenReturn(2L);
        Mockito.doReturn(true).when(accountManagerImpl).isRootAdmin(2L);

        accountManagerImpl.checkCallerApiPermissionsForUserOrAccountOperations(accountMock);
    }

    @Test
    public void testcheckCallerApiPermissionsForUserOperationsAllowedApis() {
        Mockito.lenient().when(accountManagerImpl.getCurrentCallingAccount()).thenReturn(callingAccount);
        Mockito.lenient().when(callingAccount.getAccountId()).thenReturn(3L);
        Mockito.lenient().doReturn(callingAccount).when(accountManagerImpl).getAccount(3L);
        Mockito.lenient().doReturn(false).when(accountManagerImpl).isRootAdmin(3L);

        Mockito.when(accountMock.getAccountId()).thenReturn(2L);
        Mockito.doReturn(false).when(accountManagerImpl).isRootAdmin(2L);

        Mockito.lenient().doNothing().when(accountManagerImpl).checkRoleEscalation(callingAccount, accountMock);

        accountManagerImpl.checkCallerApiPermissionsForUserOrAccountOperations(accountMock);
    }

    @Test(expected = PermissionDeniedException.class)
    public void testcheckCallerApiPermissionsForUserOperationsNotAllowedApis() {
        Mockito.lenient().when(accountManagerImpl.getCurrentCallingAccount()).thenReturn(callingAccount);
        Mockito.lenient().when(callingAccount.getAccountId()).thenReturn(3L);
        Mockito.lenient().doReturn(callingAccount).when(accountManagerImpl).getAccount(3L);
        Mockito.lenient().doReturn(false).when(accountManagerImpl).isRootAdmin(3L);

        Mockito.when(accountMock.getAccountId()).thenReturn(2L);
        Mockito.doReturn(false).when(accountManagerImpl).isRootAdmin(2L);

        Mockito.lenient().doThrow(PermissionDeniedException.class).when(accountManagerImpl).checkRoleEscalation(callingAccount, accountMock);

        accountManagerImpl.checkCallerApiPermissionsForUserOrAccountOperations(accountMock);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void testPasswordChangeRequiredWithSamlThrowsException() {
        accountManagerImpl.createUser(
                "user", "pass", "fn", "ln", "e@mail.com",
                "UTC", "acct", 1L, null,
                User.Source.SAML2, true
        );
    }

    @Test(expected = InvalidParameterValueException.class)
    public void testPasswordChangeRequiredWithLdapSourceThrows() {
        accountManagerImpl.createUser(
                "user", "pass", "fn", "ln", "e@mail.com",
                "UTC", "acct", 1L, null,
                User.Source.LDAP, true);
    }

    @Test(expected = CloudRuntimeException.class)
    public void testDomainNotFound() {
        Mockito.when(_domainMgr.getDomain(1L)).thenReturn(null);
        accountManagerImpl.createUser(
                "user", "pass", "fn", "ln", "e@mail.com",
                "UTC", "acct", 1L, null,
                User.Source.UNKNOWN, false);
    }

    @Test(expected = CloudRuntimeException.class)
    public void testCreateUserInactiveDomain() {
        Mockito.when(domainVoMock.getState()).thenReturn(Domain.State.Inactive);
        Mockito.when(_domainMgr.getDomain(Mockito.anyLong())).thenReturn(domainVoMock);
        accountManagerImpl.createUser(
                "user", "pass", "fn", "ln", "e@mail.com",
                "UTC", "acct", 1L, null,
                User.Source.NATIVE, false);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void testCreateUserCheckAccess() {
        Mockito.when(domainVoMock.getState()).thenReturn(Domain.State.Active);
        Mockito.when(_domainMgr.getDomain(Mockito.anyLong())).thenReturn(domainVoMock);
        Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.any(Account.class), Mockito.any(Domain.class));
        accountManagerImpl.createUser(
                "user", "pass", "fn", "ln", "e@mail.com",
                "UTC", "acct", 1L, null,
                User.Source.NATIVE, false);
    }

    @Test(expected = InvalidParameterValueException.class)
    public void testCreateUserMissingOrProjectAccount() {
        Mockito.when(domainVoMock.getState()).thenReturn(Domain.State.Active);
        Mockito.when(_accountDao.findEnabledAccount(Mockito.anyString(), Mockito.anyLong())).thenReturn(accountMock);
        Mockito.when(accountMock.getType()).thenReturn(Account.Type.PROJECT);
        Mockito.when(_domainMgr.getDomain(Mockito.anyLong())).thenReturn(domainVoMock);
        Mockito.doNothing().when(accountManagerImpl).checkAccess(Mockito.any(Account.class), Mockito.any(Domain.class));
        accountManagerImpl.createUser(
                "user", "pass", "fn", "ln", "e@mail.com",
                "UTC", "acct", 1L, null,
                User.Source.NATIVE, false);
    }

    @Test
    public void testCreateUserSuccess() {
        Account rootAdminAccount = Mockito.mock(Account.class);
        Mockito.when(rootAdminAccount.getId()).thenReturn(1L);
        Mockito.when(accountManagerImpl.isRootAdmin(1L)).thenReturn(true);
        User callingUser = Mockito.mock(User.class);
        CallContext.register(callingUser, rootAdminAccount);

        String newPassword = "newPassword";
        configureUserMockAuthenticators(newPassword);
        Mockito.doNothing().when(accountManagerImpl).checkAccess(any(Account.class), any(Domain.class));
        Mockito.doReturn(accountMock).when(accountManagerImpl).getAccount(Mockito.anyLong());
        Mockito.doNothing().when(passwordPolicyMock).verifyIfPasswordCompliesWithPasswordPolicies(Mockito.anyString(), Mockito.anyString(), Mockito.anyLong());
        Mockito.when(_domainMgr.getDomain(Mockito.anyLong())).thenReturn(domainVoMock);
        Mockito.when(domainVoMock.getState()).thenReturn(Domain.State.Active);

        Mockito.when(_accountDao.findEnabledAccount(Mockito.anyString(), Mockito.anyLong())).thenReturn(accountMock);
        Mockito.when(accountMock.getId()).thenReturn(10L);
        Mockito.when(accountMock.getType()).thenReturn(Account.Type.NORMAL);

        Mockito.when(userAccountDao.validateUsernameInDomain(Mockito.anyString(), Mockito.anyLong())).thenReturn(true);
        Mockito.when(userDaoMock.findUsersByName(Mockito.anyString())).thenReturn(Collections.emptyList());
        UserVO createdUser = new UserVO();
        String userMockUUID = "userMockUUID";
        createdUser.setUuid(userMockUUID);
        Mockito.when(userDaoMock.persist(Mockito.any(UserVO.class))).thenReturn(createdUser);
        UserVO userResultVO = accountManagerImpl.createUser(
                "user", newPassword, "fn", "ln", "e@mail.com",
                "UTC", "acct", 1L, null,
                User.Source.NATIVE, false
        );
        Assert.assertNotNull(userResultVO);
        UserVO userResultPasswordChangeVO = accountManagerImpl.createUser(
                "user", newPassword, "fn", "ln", "e@mail.com",
                "UTC", "acct", 1L, null,
                User.Source.NATIVE, true
        );
        Assert.assertNotNull(userResultVO);
    }
}
