// 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.nullable;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.cloudstack.acl.SecurityChecker.AccessType;
import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd;

import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.api.command.admin.user.GetUserKeysCmd;
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.webhook.WebhookHelper;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
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.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;

@RunWith(MockitoJUnitRunner.class)
public class AccountManagerImplTest extends AccountManagetImplTestBase {

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

    @Mock
    private UpdateUserCmd UpdateUserCmdMock;

    private long userVoIdMock = 111l;
    @Mock
    private UserVO userVoMock;

    private long accountMockId = 100l;

    @Mock
    private Account accountMock;

    @Mock
    private DomainVO domainVoMock;

    @Mock
    private AccountVO accountVoMock;

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

    @Mock
    PasswordPolicyImpl passwordPolicyMock;

    @Mock
    ConfigKey<Boolean> enableUserTwoFactorAuthenticationMock;

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

    @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();
    }

    @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(42l)).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(42l)).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.doNothing().when(accountManagerImpl).deleteWebhooksForAccount(Mockito.anyLong());

        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(42l)).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());

        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());

            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());
            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(userAccountDaoMock.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(_listkeyscmd.getID()).thenReturn(1L);
        Mockito.when(accountManagerImpl.getActiveUser(1L)).thenReturn(userVoMock);
        Mockito.when(userAccountDaoMock.findById(1L)).thenReturn(userAccountVO);
        Mockito.when(userAccountVO.getAccountId()).thenReturn(1L);
        Mockito.lenient().when(accountManagerImpl.getAccount(Mockito.anyLong())).thenReturn(accountMock); // Queried account - admin account

        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(_listkeyscmd);
    }

    @Test(expected = PermissionDeniedException.class)
    public void testGetUserKeysCmdDomainAdminRootAdminUser() {
        CallContext.register(callingUser, callingAccount);
        Mockito.when(_listkeyscmd.getID()).thenReturn(2L);
        Mockito.when(accountManagerImpl.getActiveUser(2L)).thenReturn(userVoMock);
        Mockito.when(userAccountDaoMock.findById(2L)).thenReturn(userAccountVO);
        Mockito.when(userAccountVO.getAccountId()).thenReturn(2L);
        Mockito.when(userDetailsDaoMock.listDetailsKeyPairs(Mockito.anyLong())).thenReturn(null);

        // Queried account - admin account
        AccountVO adminAccountMock = Mockito.mock(AccountVO.class);
        Mockito.when(adminAccountMock.getAccountId()).thenReturn(2L);
        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(_listkeyscmd);
    }

    @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() {
        prepareMockAndExecuteUpdateUserTest(0);
    }

    @Test
    public void updateUserTestTimeZoneAndEmailNotNull() {
        Mockito.when(UpdateUserCmdMock.getEmail()).thenReturn("email");
        Mockito.when(UpdateUserCmdMock.getTimezone()).thenReturn("timezone");
        prepareMockAndExecuteUpdateUserTest(1);
    }

    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.doNothing().when(accountManagerImpl).validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
        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(userAccountDaoMock).findById(Mockito.anyLong());

        accountManagerImpl.updateUser(UpdateUserCmdMock);

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

        inOrder.verify(accountManagerImpl).retrieveAndValidateUser(UpdateUserCmdMock);
        inOrder.verify(accountManagerImpl).validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
        inOrder.verify(accountManagerImpl).retrieveAndValidateAccount(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(userAccountDaoMock).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 validateAndUpdatApiAndSecretKeyIfNeededTestNoKeys() {
        accountManagerImpl.validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);

        Mockito.verify(_accountDao, Mockito.times(0)).findUserAccountByApiKey(Mockito.anyString());
    }

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

        accountManagerImpl.validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
    }

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

        accountManagerImpl.validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
    }

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

        Mockito.doReturn(1L).when(userVoMock).getId();

        User otherUserMock = Mockito.mock(User.class);
        Mockito.doReturn(2L).when(otherUserMock).getId();

        Pair<User, Account> pairUserAccountMock = new Pair<User, Account>(otherUserMock, Mockito.mock(Account.class));
        Mockito.doReturn(pairUserAccountMock).when(_accountDao).findUserAccountByApiKey(apiKey);

        accountManagerImpl.validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);
    }

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

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

        Mockito.doReturn(1L).when(userVoMock).getId();

        User otherUserMock = Mockito.mock(User.class);
        Mockito.doReturn(1L).when(otherUserMock).getId();

        Pair<User, Account> pairUserAccountMock = new Pair<User, Account>(otherUserMock, Mockito.mock(Account.class));
        Mockito.doReturn(pairUserAccountMock).when(_accountDao).findUserAccountByApiKey(apiKey);

        accountManagerImpl.validateAndUpdateApiAndSecretKeyIfNeeded(UpdateUserCmdMock, userVoMock);

        Mockito.verify(_accountDao).findUserAccountByApiKey(apiKey);
        Mockito.verify(userVoMock).setApiKey(apiKey);
        Mockito.verify(userVoMock).setSecretKey(secretKey);
    }

    @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(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(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);
    }

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