// 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.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);
    }
}
