/*
 * 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.epam.dlab.backendapi.service.impl;

import com.epam.dlab.auth.UserInfo;
import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
import com.epam.dlab.backendapi.dao.ComputationalDAO;
import com.epam.dlab.backendapi.dao.ExploratoryDAO;
import com.epam.dlab.backendapi.domain.EndpointDTO;
import com.epam.dlab.backendapi.domain.ProjectDTO;
import com.epam.dlab.backendapi.domain.ProjectEndpointDTO;
import com.epam.dlab.backendapi.domain.RequestId;
import com.epam.dlab.backendapi.resources.dto.ComputationalCreateFormDTO;
import com.epam.dlab.backendapi.resources.dto.SparkStandaloneClusterCreateForm;
import com.epam.dlab.backendapi.service.EndpointService;
import com.epam.dlab.backendapi.service.ProjectService;
import com.epam.dlab.backendapi.service.TagService;
import com.epam.dlab.backendapi.util.RequestBuilder;
import com.epam.dlab.cloud.CloudProvider;
import com.epam.dlab.dto.SchedulerJobDTO;
import com.epam.dlab.dto.UserInstanceDTO;
import com.epam.dlab.dto.UserInstanceStatus;
import com.epam.dlab.dto.aws.computational.ClusterConfig;
import com.epam.dlab.dto.base.computational.ComputationalBase;
import com.epam.dlab.dto.base.edge.EdgeInfo;
import com.epam.dlab.dto.computational.ComputationalClusterConfigDTO;
import com.epam.dlab.dto.computational.ComputationalStartDTO;
import com.epam.dlab.dto.computational.ComputationalStatusDTO;
import com.epam.dlab.dto.computational.ComputationalStopDTO;
import com.epam.dlab.dto.computational.ComputationalTerminateDTO;
import com.epam.dlab.dto.computational.SparkStandaloneClusterResource;
import com.epam.dlab.dto.computational.UserComputationalResource;
import com.epam.dlab.exceptions.DlabException;
import com.epam.dlab.exceptions.ResourceNotFoundException;
import com.epam.dlab.rest.client.RESTService;
import com.epam.dlab.rest.contracts.ComputationalAPI;
import com.mongodb.client.result.UpdateResult;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import static com.epam.dlab.dto.UserInstanceStatus.CREATING;
import static com.epam.dlab.dto.UserInstanceStatus.RUNNING;
import static com.epam.dlab.dto.UserInstanceStatus.STOPPED;
import static java.util.Collections.singletonList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyListOf;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.refEq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;


@RunWith(MockitoJUnitRunner.class)
public class ComputationalServiceImplTest {

    private static final long MAX_INACTIVITY = 10L;
    private static final String DOCKER_DLAB_DATAENGINE = "docker.dlab-dataengine";
    private static final String DOCKER_DLAB_DATAENGINE_SERVICE = "docker.dlab-dataengine-service";
    private static final String COMP_ID = "compId";
    private final String USER = "test";
    private final String TOKEN = "token";
    private final String EXPLORATORY_NAME = "expName";
    private final String PROJECT = "project";
    private final String COMP_NAME = "compName";
    private final String UUID = "1234-56789765-4321";
    private final LocalDateTime LAST_ACTIVITY = LocalDateTime.now().minusMinutes(MAX_INACTIVITY);

    private UserInfo userInfo;
    private List<ComputationalCreateFormDTO> formList;
    private UserInstanceDTO userInstance;
    private ComputationalStatusDTO computationalStatusDTOWithStatusTerminating;
    private ComputationalStatusDTO computationalStatusDTOWithStatusFailed;
    private ComputationalStatusDTO computationalStatusDTOWithStatusStopping;
    private ComputationalStatusDTO computationalStatusDTOWithStatusStarting;
    private SparkStandaloneClusterResource sparkClusterResource;
    private UserComputationalResource ucResource;

    @Mock
    private ProjectService projectService;
    @Mock
    private ExploratoryDAO exploratoryDAO;
    @Mock
    private ComputationalDAO computationalDAO;
	@Mock
	private RESTService provisioningService;
	@Mock
	private SelfServiceApplicationConfiguration configuration;
	@Mock
	private RequestBuilder requestBuilder;
	@Mock
	private RequestId requestId;
	@Mock
	private TagService tagService;
	@Mock
	private EndpointService endpointService;

	@InjectMocks
	private ComputationalServiceImpl computationalService;

	@Rule
	public ExpectedException expectedException = ExpectedException.none();

	@Before
	public void setUp() {
		userInfo = getUserInfo();
		userInstance = getUserInstanceDto();
		formList = getFormList();
		computationalStatusDTOWithStatusTerminating = getComputationalStatusDTOWithStatus("terminating");
		computationalStatusDTOWithStatusFailed = getComputationalStatusDTOWithStatus("failed");
		computationalStatusDTOWithStatusStopping = getComputationalStatusDTOWithStatus("stopping");
		computationalStatusDTOWithStatusStarting = getComputationalStatusDTOWithStatus("starting");
		sparkClusterResource = getSparkClusterResource();
		ucResource = getUserComputationalResource(STOPPED, DOCKER_DLAB_DATAENGINE);
	}

	@Test
	public void createSparkCluster() {
        ProjectDTO projectDTO = getProjectDTO();
        when(projectService.get(anyString())).thenReturn(projectDTO);
        when(endpointService.get(anyString())).thenReturn(endpointDTO());
        when(computationalDAO.addComputational(anyString(), anyString(), anyString(),
                any(SparkStandaloneClusterResource.class))).thenReturn(true);
        when(exploratoryDAO.fetchExploratoryFields(anyString(), anyString(), anyString())).thenReturn(userInstance);

        ComputationalBase compBaseMocked = mock(ComputationalBase.class);
        when(requestBuilder.newComputationalCreate(any(UserInfo.class), any(ProjectDTO.class),
                any(UserInstanceDTO.class), any(SparkStandaloneClusterCreateForm.class), any(EndpointDTO.class)))
                .thenReturn(compBaseMocked);
        when(provisioningService.post(anyString(), anyString(), any(ComputationalBase.class), any())).thenReturn(UUID);
        when(requestId.put(anyString(), anyString())).thenReturn(UUID);

        SparkStandaloneClusterCreateForm sparkClusterCreateForm = (SparkStandaloneClusterCreateForm) formList.get(0);
        boolean creationResult =
                computationalService.createSparkCluster(userInfo, sparkClusterCreateForm, PROJECT);
        assertTrue(creationResult);

        verify(projectService).get(PROJECT);
        verify(computationalDAO).addComputational(eq(USER), eq(EXPLORATORY_NAME), eq(PROJECT), refEq(sparkClusterResource));

        verify(exploratoryDAO).fetchExploratoryFields(USER, PROJECT, EXPLORATORY_NAME);
        verify(requestBuilder).newComputationalCreate(
                refEq(userInfo), refEq(projectDTO), refEq(userInstance), refEq(sparkClusterCreateForm), refEq(endpointDTO()));

        verify(provisioningService)
                .post(endpointDTO().getUrl() + ComputationalAPI.COMPUTATIONAL_CREATE_SPARK, TOKEN, compBaseMocked,
                        String.class);

        verify(requestId).put(USER, UUID);
        verifyNoMoreInteractions(projectService, configuration, computationalDAO, requestBuilder, provisioningService, requestId);
    }

    @Test
    public void createSparkClusterWhenResourceAlreadyExists() {
        when(computationalDAO.addComputational(anyString(), anyString(), anyString(),
                any(SparkStandaloneClusterResource.class))).thenReturn(false);
        when(exploratoryDAO.fetchExploratoryFields(anyString(), anyString(), anyString())).thenReturn(userInstance);


        boolean creationResult = computationalService.createSparkCluster(userInfo, (SparkStandaloneClusterCreateForm) formList.get(0),
                PROJECT);
        assertFalse(creationResult);

        verify(computationalDAO).addComputational(eq(USER), eq(EXPLORATORY_NAME), eq(PROJECT), refEq(sparkClusterResource));
        verifyNoMoreInteractions(configuration, computationalDAO);
    }

	@Test
	public void createSparkClusterWhenMethodFetchExploratoryFieldsThrowsException() {
        when(computationalDAO.addComputational(anyString(), anyString(), anyString(),
                any(SparkStandaloneClusterResource.class))).thenReturn(true);
        doThrow(new ResourceNotFoundException("Exploratory for user with name not found"))
                .when(exploratoryDAO).fetchExploratoryFields(anyString(), anyString(), anyString());

        when(computationalDAO.updateComputationalStatus(any(ComputationalStatusDTO.class)))
                .thenReturn(mock(UpdateResult.class));

        SparkStandaloneClusterCreateForm sparkClusterCreateForm = (SparkStandaloneClusterCreateForm) formList.get(0);
        try {
            computationalService.createSparkCluster(userInfo, sparkClusterCreateForm, PROJECT);
        } catch (ResourceNotFoundException e) {
            assertEquals("Exploratory for user with name not found", e.getMessage());
        }

        verify(computationalDAO, never()).addComputational(USER, EXPLORATORY_NAME, PROJECT, sparkClusterResource);
        verify(computationalDAO, never()).updateComputationalStatus(refEq(computationalStatusDTOWithStatusFailed,
                "self"));
        verify(exploratoryDAO).fetchExploratoryFields(USER, PROJECT, EXPLORATORY_NAME);
        verifyNoMoreInteractions(configuration, computationalDAO, exploratoryDAO);
    }

	@Test
	public void createSparkClusterWhenMethodNewComputationalCreateThrowsException() {
        ProjectDTO projectDTO = getProjectDTO();
        when(endpointService.get(anyString())).thenReturn(endpointDTO());
        when(projectService.get(anyString())).thenReturn(projectDTO);
        when(computationalDAO.addComputational(anyString(), anyString(), anyString(),
                any(SparkStandaloneClusterResource.class))).thenReturn(true);
        when(exploratoryDAO.fetchExploratoryFields(anyString(), anyString(), anyString())).thenReturn(userInstance);

        doThrow(new DlabException("Cannot create instance of resource class "))
                .when(requestBuilder).newComputationalCreate(any(UserInfo.class), any(ProjectDTO.class),
                any(UserInstanceDTO.class), any(SparkStandaloneClusterCreateForm.class), any(EndpointDTO.class));

        when(computationalDAO.updateComputationalStatus(any(ComputationalStatusDTO.class)))
                .thenReturn(mock(UpdateResult.class));

        SparkStandaloneClusterCreateForm sparkClusterCreateForm = (SparkStandaloneClusterCreateForm) formList.get(0);
        try {
            computationalService.createSparkCluster(userInfo, sparkClusterCreateForm, PROJECT);
        } catch (DlabException e) {
            assertEquals("Cannot create instance of resource class ", e.getMessage());
        }
        verify(projectService).get(PROJECT);
        verify(computationalDAO).addComputational(USER, EXPLORATORY_NAME, PROJECT, sparkClusterResource);
        verify(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusFailed, "self"));
        verify(exploratoryDAO).fetchExploratoryFields(USER, PROJECT, EXPLORATORY_NAME);
        verify(requestBuilder).newComputationalCreate(userInfo, projectDTO, userInstance, sparkClusterCreateForm, endpointDTO());
        verifyNoMoreInteractions(projectService, configuration, computationalDAO, exploratoryDAO, requestBuilder);
    }

	@Test
	public void terminateComputationalEnvironment() {
        when(endpointService.get(anyString())).thenReturn(endpointDTO());
        when(computationalDAO.updateComputationalStatus(any(ComputationalStatusDTO.class)))
                .thenReturn(mock(UpdateResult.class));
        String explId = "explId";
        when(exploratoryDAO.fetchExploratoryFields(anyString(), anyString(), anyString())).thenReturn(userInstance);

        String compId = "compId";
        UserComputationalResource ucResource = new UserComputationalResource();
        ucResource.setComputationalName(COMP_NAME);
        ucResource.setImageName("dataengine-service");
        ucResource.setComputationalId(compId);
        when(computationalDAO.fetchComputationalFields(anyString(), anyString(), anyString(), anyString())).thenReturn(ucResource);

        ComputationalTerminateDTO ctDto = new ComputationalTerminateDTO();
        ctDto.setComputationalName(COMP_NAME);
        ctDto.setExploratoryName(EXPLORATORY_NAME);
        when(requestBuilder.newComputationalTerminate(any(UserInfo.class), any(UserInstanceDTO.class),
                any(UserComputationalResource.class), any(EndpointDTO.class))).thenReturn(ctDto);

        when(provisioningService.post(anyString(), anyString(), any(ComputationalTerminateDTO.class), any()))
                .thenReturn(UUID);
        when(requestId.put(anyString(), anyString())).thenReturn(UUID);

        computationalService.terminateComputational(userInfo, PROJECT, EXPLORATORY_NAME, COMP_NAME);

        verify(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusTerminating, "self"));
        verify(computationalDAO).fetchComputationalFields(USER, PROJECT, EXPLORATORY_NAME, COMP_NAME);

        verify(requestBuilder).newComputationalTerminate(userInfo, userInstance, ucResource, endpointDTO());

        verify(provisioningService).post(endpointDTO().getUrl() + ComputationalAPI.COMPUTATIONAL_TERMINATE_CLOUD_SPECIFIC, TOKEN, ctDto,
                String.class);

        verify(requestId).put(USER, UUID);
        verify(exploratoryDAO).fetchExploratoryFields(USER, PROJECT, EXPLORATORY_NAME);
        verifyNoMoreInteractions(computationalDAO, exploratoryDAO, requestBuilder, provisioningService, requestId);
    }

	@Test
	public void terminateComputationalEnvironmentWhenMethodUpdateComputationalStatusThrowsException() {
		doThrow(new DlabException("Could not update computational resource status"))
				.when(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusTerminating,
				"self"));

		when(computationalDAO.updateComputationalStatus(refEq(computationalStatusDTOWithStatusFailed, "self")))
				.thenReturn(mock(UpdateResult.class));

        try {
            computationalService.terminateComputational(userInfo, PROJECT, EXPLORATORY_NAME, COMP_NAME);
        } catch (DlabException e) {
            assertEquals("Could not update computational resource status", e.getMessage());
        }

		verify(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusTerminating, "self"));
		verify(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusFailed, "self"));
		verifyNoMoreInteractions(computationalDAO);
	}

	@Test
	public void terminateComputationalEnvironmentWhenMethodFetchComputationalFieldsThrowsException() {
        when(computationalDAO.updateComputationalStatus(any(ComputationalStatusDTO.class)))
                .thenReturn(mock(UpdateResult.class));

        doThrow(new DlabException("Computational resource for user with exploratory name not found."))
                .when(computationalDAO).fetchComputationalFields(anyString(), anyString(), anyString(), anyString());
        when(computationalDAO.updateComputationalStatus(any(ComputationalStatusDTO.class)))
                .thenReturn(mock(UpdateResult.class));

        try {
            computationalService.terminateComputational(userInfo, PROJECT, EXPLORATORY_NAME, COMP_NAME);
        } catch (DlabException e) {
            assertEquals("Computational resource for user with exploratory name not found.", e.getMessage());
        }

        verify(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusTerminating, "self"));
        verify(computationalDAO).fetchComputationalFields(USER, PROJECT, EXPLORATORY_NAME, COMP_NAME);
        verify(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusFailed, "self"));
        verify(exploratoryDAO).fetchExploratoryFields(USER, PROJECT, EXPLORATORY_NAME);
        verifyNoMoreInteractions(computationalDAO, exploratoryDAO);
    }

	@Test
	public void terminateComputationalEnvironmentWhenMethodNewComputationalTerminateThrowsException() {
        when(endpointService.get(anyString())).thenReturn(endpointDTO());
        when(computationalDAO.updateComputationalStatus(any(ComputationalStatusDTO.class)))
                .thenReturn(mock(UpdateResult.class));
        when(exploratoryDAO.fetchExploratoryFields(anyString(), anyString(), anyString())).thenReturn(userInstance);

        String compId = "compId";
        UserComputationalResource ucResource = new UserComputationalResource();
        ucResource.setComputationalName(COMP_NAME);
        ucResource.setImageName("dataengine-service");
        ucResource.setComputationalId(compId);
        when(computationalDAO.fetchComputationalFields(anyString(), anyString(), anyString(), anyString())).thenReturn(ucResource);

        doThrow(new DlabException("Cannot create instance of resource class "))
                .when(requestBuilder).newComputationalTerminate(any(UserInfo.class), any(UserInstanceDTO.class),
                any(UserComputationalResource.class), any(EndpointDTO.class));

        when(computationalDAO.updateComputationalStatus(any(ComputationalStatusDTO.class)))
                .thenReturn(mock(UpdateResult.class));

        try {
            computationalService.terminateComputational(userInfo, PROJECT, EXPLORATORY_NAME, COMP_NAME);
        } catch (DlabException e) {
            assertEquals("Cannot create instance of resource class ", e.getMessage());
        }

        verify(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusTerminating, "self"));
        verify(computationalDAO).fetchComputationalFields(USER, PROJECT, EXPLORATORY_NAME, COMP_NAME);

        verify(exploratoryDAO).fetchExploratoryFields(USER, PROJECT, EXPLORATORY_NAME);

        verify(requestBuilder).newComputationalTerminate(userInfo, userInstance, ucResource, endpointDTO());
        verify(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusFailed, "self"));
        verifyNoMoreInteractions(computationalDAO, exploratoryDAO, requestBuilder);
    }

	@Test
	public void createDataEngineService() {
        ProjectDTO projectDTO = getProjectDTO();
        when(projectService.get(anyString())).thenReturn(projectDTO);
        when(endpointService.get(anyString())).thenReturn(endpointDTO());
        when(computationalDAO.addComputational(anyString(), anyString(), anyString(), any(UserComputationalResource.class)))
                .thenReturn(true);
        when(exploratoryDAO.fetchExploratoryFields(anyString(), anyString(), anyString())).thenReturn(userInstance);

        ComputationalBase compBaseMocked = mock(ComputationalBase.class);
        when(requestBuilder.newComputationalCreate(any(UserInfo.class), any(ProjectDTO.class),
                any(UserInstanceDTO.class), any(ComputationalCreateFormDTO.class), any(EndpointDTO.class)))
                .thenReturn(compBaseMocked);

        when(provisioningService.post(anyString(), anyString(), any(ComputationalBase.class), any())).thenReturn(UUID);
        when(requestId.put(anyString(), anyString())).thenReturn(UUID);

        boolean creationResult =
                computationalService.createDataEngineService(userInfo, formList.get(1), ucResource, PROJECT);
        assertTrue(creationResult);

        verify(projectService).get(PROJECT);

        verify(computationalDAO).addComputational(eq(USER), eq(EXPLORATORY_NAME), eq(PROJECT), refEq(ucResource));

        verify(exploratoryDAO).fetchExploratoryFields(USER, PROJECT, EXPLORATORY_NAME);

        verify(requestBuilder).newComputationalCreate(
                refEq(userInfo), refEq(projectDTO), refEq(userInstance), any(ComputationalCreateFormDTO.class), refEq(endpointDTO()));

        verify(provisioningService)
                .post(endpointDTO().getUrl() + ComputationalAPI.COMPUTATIONAL_CREATE_CLOUD_SPECIFIC, TOKEN,
                        compBaseMocked, String.class);

        verify(requestId).put(USER, UUID);
        verifyNoMoreInteractions(projectService, computationalDAO, exploratoryDAO, requestBuilder, provisioningService, requestId);
    }

	@Test
	public void createDataEngineServiceWhenComputationalResourceNotAdded() {
        when(exploratoryDAO.fetchExploratoryFields(anyString(), anyString(), anyString())).thenReturn(userInstance);
        when(computationalDAO.addComputational(anyString(), anyString(), any(), any(UserComputationalResource.class)))
                .thenReturn(false);

        boolean creationResult = computationalService.createDataEngineService(userInfo, formList.get(1), ucResource,
                PROJECT);
        assertFalse(creationResult);

        verify(computationalDAO).addComputational(eq(USER), eq(EXPLORATORY_NAME), eq(PROJECT), refEq(ucResource));
        verifyNoMoreInteractions(computationalDAO);
    }

	@Test
	public void createDataEngineServiceWhenMethodFetchExploratoryFieldsThrowsException() {
        when(computationalDAO.addComputational(anyString(), anyString(), anyString(), any(UserComputationalResource.class)))
                .thenReturn(true);
        doThrow(new ResourceNotFoundException("Exploratory for user with name not found"))
                .when(exploratoryDAO).fetchExploratoryFields(anyString(), anyString(), anyString());

        when(computationalDAO.updateComputationalStatus(any(ComputationalStatusDTO.class)))
                .thenReturn(mock(UpdateResult.class));

        try {
            computationalService.createDataEngineService(userInfo, formList.get(1), ucResource, PROJECT);
        } catch (DlabException e) {
            assertEquals("Exploratory for user with name not found", e.getMessage());
        }

        verify(computationalDAO, never())
                .addComputational(eq(USER), eq(EXPLORATORY_NAME), eq(PROJECT), refEq(ucResource));

        verify(exploratoryDAO).fetchExploratoryFields(USER, PROJECT, EXPLORATORY_NAME);

        verify(computationalDAO, never()).updateComputationalStatus(refEq(computationalStatusDTOWithStatusFailed,
                "self"));
        verifyNoMoreInteractions(computationalDAO, exploratoryDAO);
    }

	@Test
	public void createDataEngineServiceWhenMethodNewComputationalCreateThrowsException() {
        ProjectDTO projectDTO = getProjectDTO();
        when(projectService.get(anyString())).thenReturn(projectDTO);
        when(endpointService.get(anyString())).thenReturn(endpointDTO());
        when(computationalDAO.addComputational(anyString(), anyString(), any(), any(UserComputationalResource.class)))
                .thenReturn(true);
        when(exploratoryDAO.fetchExploratoryFields(anyString(), anyString(), anyString())).thenReturn(userInstance);

        doThrow(new DlabException("Cannot create instance of resource class "))
                .when(requestBuilder).newComputationalCreate(any(UserInfo.class), any(ProjectDTO.class),
                any(UserInstanceDTO.class), any(ComputationalCreateFormDTO.class), any(EndpointDTO.class));

        when(computationalDAO.updateComputationalStatus(any(ComputationalStatusDTO.class)))
                .thenReturn(mock(UpdateResult.class));

        ComputationalCreateFormDTO computationalCreateFormDTO = formList.get(1);
        try {
            computationalService.createDataEngineService(userInfo, computationalCreateFormDTO, ucResource, PROJECT);
        } catch (DlabException e) {
            assertEquals("Could not send request for creation the computational resource compName: " +
                    "Cannot create instance of resource class ", e.getMessage());
        }

        verify(projectService).get(PROJECT);
        verify(computationalDAO).addComputational(eq(USER), eq(EXPLORATORY_NAME), eq(PROJECT), refEq(ucResource));
        verify(exploratoryDAO).fetchExploratoryFields(USER, PROJECT, EXPLORATORY_NAME);
        verify(requestBuilder).newComputationalCreate(
                refEq(userInfo), refEq(projectDTO), refEq(userInstance), refEq(computationalCreateFormDTO), refEq(endpointDTO()));
        verify(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusFailed, "self"));

        verifyNoMoreInteractions(projectService, computationalDAO, exploratoryDAO, requestBuilder);
    }

	@Test
	public void stopSparkCluster() {
        final UserInstanceDTO exploratory = getUserInstanceDto();
        exploratory.setResources(singletonList(getUserComputationalResource(RUNNING, DOCKER_DLAB_DATAENGINE)));
        when(endpointService.get(anyString())).thenReturn(endpointDTO());
        when(exploratoryDAO.fetchExploratoryFields(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(exploratory);
        when(computationalDAO.updateComputationalStatus(any(ComputationalStatusDTO.class)))
                .thenReturn(mock(UpdateResult.class));

        ComputationalStopDTO computationalStopDTO = new ComputationalStopDTO();
        when(requestBuilder.newComputationalStop(any(UserInfo.class), any(UserInstanceDTO.class), anyString(),
                any(EndpointDTO.class))).thenReturn(computationalStopDTO);
        when(provisioningService.post(anyString(), anyString(), any(ComputationalBase.class), any()))
                .thenReturn("someUuid");
        when(requestId.put(anyString(), anyString())).thenReturn("someUuid");

        computationalService.stopSparkCluster(userInfo, PROJECT, EXPLORATORY_NAME, COMP_NAME);

        verify(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusStopping, "self"));
        verify(exploratoryDAO).fetchExploratoryFields(USER, PROJECT, EXPLORATORY_NAME, true);
        verify(requestBuilder).newComputationalStop(refEq(userInfo), refEq(exploratory), eq(COMP_NAME), refEq(endpointDTO()));
        verify(provisioningService)
                .post(eq(endpointDTO().getUrl() + "computational/stop/spark"), eq(TOKEN), refEq(computationalStopDTO),
                        eq(String.class));
        verify(requestId).put(USER, "someUuid");
        verifyNoMoreInteractions(computationalDAO, exploratoryDAO, requestBuilder,
                provisioningService, requestId);
    }

	@Test
	public void stopSparkClusterWhenDataengineTypeIsAnother() {
        final UserInstanceDTO exploratory = getUserInstanceDto();
        exploratory.setResources(singletonList(getUserComputationalResource(RUNNING, DOCKER_DLAB_DATAENGINE_SERVICE)));
        when(exploratoryDAO.fetchExploratoryFields(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(exploratory);
        expectedException.expect(IllegalStateException.class);
        expectedException.expectMessage("There is no running dataengine compName for exploratory expName");

        computationalService.stopSparkCluster(userInfo, PROJECT, EXPLORATORY_NAME, COMP_NAME);
    }

	@Test
	public void startSparkCluster() {
        when(endpointService.get(anyString())).thenReturn(endpointDTO());
        final UserInstanceDTO exploratory = getUserInstanceDto();
        exploratory.setResources(singletonList(getUserComputationalResource(STOPPED, DOCKER_DLAB_DATAENGINE)));
        when(exploratoryDAO.fetchExploratoryFields(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(exploratory);
        when(computationalDAO.updateComputationalStatus(any(ComputationalStatusDTO.class)))
                .thenReturn(mock(UpdateResult.class));

        ComputationalStartDTO computationalStartDTO = new ComputationalStartDTO();
        when(requestBuilder.newComputationalStart(any(UserInfo.class), any(UserInstanceDTO.class), anyString(),
                any(EndpointDTO.class))).thenReturn(computationalStartDTO);
        when(provisioningService.post(anyString(), anyString(), any(ComputationalBase.class), any()))
                .thenReturn("someUuid");
        when(requestId.put(anyString(), anyString())).thenReturn("someUuid");

        computationalService.startSparkCluster(userInfo, EXPLORATORY_NAME, COMP_NAME, PROJECT);

        verify(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusStarting, "self"));
        verify(exploratoryDAO).fetchExploratoryFields(USER, PROJECT, EXPLORATORY_NAME, true);
        verify(requestBuilder).newComputationalStart(refEq(userInfo), refEq(exploratory), eq(COMP_NAME), refEq(endpointDTO()));
        verify(provisioningService)
                .post(eq(endpointDTO().getUrl() + "computational/start/spark"), eq(TOKEN),
                        refEq(computationalStartDTO),
                        eq(String.class));
        verify(requestId).put(USER, "someUuid");
        verifyNoMoreInteractions(computationalDAO, exploratoryDAO, requestBuilder,
                provisioningService, requestId);
    }

	@Test
	public void startSparkClusterWhenDataengineStatusIsRunning() {
        final UserInstanceDTO userInstanceDto = getUserInstanceDto();
        userInstanceDto.setResources(singletonList(getUserComputationalResource(RUNNING,
                DOCKER_DLAB_DATAENGINE_SERVICE)));
        when(exploratoryDAO.fetchExploratoryFields(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(userInstanceDto);

        expectedException.expect(IllegalStateException.class);
        expectedException.expectMessage("There is no stopped dataengine compName for exploratory expName");

        computationalService.startSparkCluster(userInfo, EXPLORATORY_NAME, COMP_NAME, PROJECT);
    }

	@Test
	public void getComputationalResource() {
        when(computationalDAO.fetchComputationalFields(anyString(), anyString(), anyString(), anyString())).thenReturn(ucResource);

        Optional<UserComputationalResource> expectedResource = Optional.of(ucResource);
        Optional<UserComputationalResource> actualResource =
                computationalService.getComputationalResource(USER, PROJECT, EXPLORATORY_NAME, COMP_NAME);
        assertEquals(expectedResource, actualResource);

        verify(computationalDAO).fetchComputationalFields(USER, PROJECT, EXPLORATORY_NAME, COMP_NAME);
        verifyNoMoreInteractions(computationalDAO);
    }

	@Test
	public void getComputationalResourceWithException() {
        doThrow(new DlabException("Computational resource not found"))
                .when(computationalDAO).fetchComputationalFields(anyString(), anyString(), anyString(), anyString());

        Optional<UserComputationalResource> expectedResource = Optional.empty();
        Optional<UserComputationalResource> actualResource =
                computationalService.getComputationalResource(USER, PROJECT, EXPLORATORY_NAME, COMP_NAME);
        assertEquals(expectedResource, actualResource);

        verify(computationalDAO).fetchComputationalFields(USER, PROJECT, EXPLORATORY_NAME, COMP_NAME);
        verifyNoMoreInteractions(computationalDAO);
    }

	@Test
	public void testUpdateSparkClusterConfig() {
        when(endpointService.get(anyString())).thenReturn(endpointDTO());
        final ComputationalClusterConfigDTO clusterConfigDTO = new ComputationalClusterConfigDTO();
        final UserInstanceDTO userInstanceDto = getUserInstanceDto();
        final List<ClusterConfig> config = Collections.singletonList(new ClusterConfig());
        userInstanceDto.setResources(Collections.singletonList(getUserComputationalResource(RUNNING, COMP_NAME)));
        when(exploratoryDAO.fetchExploratoryFields(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(userInstanceDto);
        when(requestBuilder.newClusterConfigUpdate(any(UserInfo.class), any(UserInstanceDTO.class),
                any(UserComputationalResource.class), anyListOf(ClusterConfig.class), any(EndpointDTO.class)))
                .thenReturn(clusterConfigDTO);
        when(provisioningService.post(anyString(), anyString(), any(ComputationalClusterConfigDTO.class), any()))
                .thenReturn("someUuid");
        computationalService.updateSparkClusterConfig(getUserInfo(), PROJECT, EXPLORATORY_NAME,
                COMP_NAME, config);

        verify(exploratoryDAO).fetchExploratoryFields(USER, PROJECT, EXPLORATORY_NAME, true);
        verify(requestBuilder).newClusterConfigUpdate(refEq(getUserInfo()), refEq(userInstanceDto),
                refEq(getUserComputationalResource(RUNNING, COMP_NAME)),
                eq(Collections.singletonList(new ClusterConfig())), eq(endpointDTO()));
        verify(requestId).put(USER, "someUuid");
        verify(computationalDAO).updateComputationalFields(refEq(new ComputationalStatusDTO()
                .withProject(PROJECT)
                .withConfig(config)
                .withUser(USER)
                .withExploratoryName(EXPLORATORY_NAME)
                .withComputationalName(COMP_NAME)
                .withStatus(UserInstanceStatus.RECONFIGURING.toString()), "self"));
        verify(provisioningService).post(eq(endpointDTO().getUrl() + "computational/spark/reconfigure"),
                eq(getUserInfo().getAccessToken()),
                refEq(new ComputationalClusterConfigDTO()), eq(String.class));

    }

	@Test
	public void testUpdateSparkClusterConfigWhenClusterIsNotRunning() {
        final UserInstanceDTO userInstanceDto = getUserInstanceDto();
        final List<ClusterConfig> config = Collections.singletonList(new ClusterConfig());
        userInstanceDto.setResources(Collections.singletonList(getUserComputationalResource(STOPPED, COMP_NAME)));
        when(exploratoryDAO.fetchExploratoryFields(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(userInstanceDto);
        try {
            computationalService.updateSparkClusterConfig(getUserInfo(), PROJECT, EXPLORATORY_NAME,
                    COMP_NAME, config);
        } catch (ResourceNotFoundException e) {
            assertEquals("Running computational resource with name compName for exploratory expName not found",
                    e.getMessage());
        }

        verify(exploratoryDAO).fetchExploratoryFields(USER, PROJECT, EXPLORATORY_NAME, true);
        verifyNoMoreInteractions(exploratoryDAO);
        verifyZeroInteractions(provisioningService, requestBuilder, requestId);

    }

	@Test
	public void testUpdateSparkClusterConfigWhenClusterIsNotFound() {
        final UserInstanceDTO userInstanceDto = getUserInstanceDto();
        final List<ClusterConfig> config = Collections.singletonList(new ClusterConfig());
        userInstanceDto.setResources(Collections.singletonList(getUserComputationalResource(STOPPED, COMP_NAME)));
        when(exploratoryDAO.fetchExploratoryFields(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(userInstanceDto);
        try {
            computationalService.updateSparkClusterConfig(getUserInfo(), PROJECT, EXPLORATORY_NAME,
                    COMP_NAME + "X", config);
        } catch (ResourceNotFoundException e) {
            assertEquals("Running computational resource with name compNameX for exploratory expName not found",
                    e.getMessage());
        }

        verify(exploratoryDAO).fetchExploratoryFields(USER, PROJECT, EXPLORATORY_NAME, true);
        verifyNoMoreInteractions(exploratoryDAO);
        verifyZeroInteractions(provisioningService, requestBuilder, requestId);

    }

	@Test
	public void testGetClusterConfig() {
        when(computationalDAO.getClusterConfig(anyString(), anyString(), anyString(), anyString())).thenReturn(Collections.singletonList(getClusterConfig()));

        final List<ClusterConfig> clusterConfig = computationalService.getClusterConfig(getUserInfo(), PROJECT,
                EXPLORATORY_NAME, COMP_NAME);
        final ClusterConfig config = clusterConfig.get(0);

        assertEquals(1, clusterConfig.size());
        assertEquals("test", config.getClassification());
        assertNull(config.getConfigurations());
        assertNull(config.getProperties());
    }


	@Test
	public void testGetClusterConfigWithException() {
        when(computationalDAO.getClusterConfig(anyString(), anyString(), anyString(), anyString())).thenThrow(new RuntimeException(
                "Exception"));

        expectedException.expectMessage("Exception");
        expectedException.expect(RuntimeException.class);
        computationalService.getClusterConfig(getUserInfo(), PROJECT, EXPLORATORY_NAME, COMP_NAME);
    }

	private ClusterConfig getClusterConfig() {
		final ClusterConfig config = new ClusterConfig();
		config.setClassification("test");
		return config;
	}

	private UserInfo getUserInfo() {
		return new UserInfo(USER, TOKEN);
	}

	private UserInstanceDTO getUserInstanceDto() {
		return new UserInstanceDTO().withUser(USER).withExploratoryName(EXPLORATORY_NAME)
                .withExploratoryId("explId")
                .withProject(PROJECT)
				.withTags(Collections.emptyMap());
	}

	private List<ComputationalCreateFormDTO> getFormList() {
        SparkStandaloneClusterCreateForm sparkClusterForm = new SparkStandaloneClusterCreateForm();
        sparkClusterForm.setNotebookName(EXPLORATORY_NAME);
        sparkClusterForm.setName(COMP_NAME);
        sparkClusterForm.setProject(PROJECT);
        sparkClusterForm.setDataEngineInstanceCount(String.valueOf(2));
        sparkClusterForm.setImage("dataengine");
        ComputationalCreateFormDTO desClusterForm = new ComputationalCreateFormDTO();
        desClusterForm.setNotebookName(EXPLORATORY_NAME);
        desClusterForm.setName(COMP_NAME);

        return Arrays.asList(sparkClusterForm, desClusterForm);
    }

	private ComputationalStatusDTO getComputationalStatusDTOWithStatus(String status) {
		return new ComputationalStatusDTO()
                .withUser(USER)
                .withProject(PROJECT)
				.withExploratoryName(EXPLORATORY_NAME)
				.withComputationalName(COMP_NAME)
				.withStatus(UserInstanceStatus.of(status));
	}

	private SparkStandaloneClusterResource getSparkClusterResource() {
		return SparkStandaloneClusterResource.builder()
				.computationalName(COMP_NAME)
				.imageName("dataengine")
				.status(CREATING.toString())
				.dataEngineInstanceCount(String.valueOf(2))
				.tags(Collections.emptyMap())
				.build();
	}

	private EndpointDTO endpointDTO() {
		return new EndpointDTO("test", "url", "", null, EndpointDTO.EndpointStatus.ACTIVE, CloudProvider.AWS);
	}


	private UserComputationalResource getUserComputationalResource(UserInstanceStatus status, String imageName) {
		UserComputationalResource ucResource = new UserComputationalResource();
		ucResource.setComputationalName(COMP_NAME);
		ucResource.setImageName("dataengine");
		ucResource.setImageName(imageName);
		ucResource.setStatus(status.toString());
		ucResource.setLastActivity(LAST_ACTIVITY);
		ucResource.setComputationalId(COMP_ID);
		ucResource.setTags(Collections.emptyMap());
		final SchedulerJobDTO schedulerData = new SchedulerJobDTO();
		schedulerData.setCheckInactivityRequired(true);
		schedulerData.setMaxInactivity(MAX_INACTIVITY);
		ucResource.setSchedulerData(schedulerData);
		return ucResource;
	}

	private ProjectDTO getProjectDTO() {
        return new ProjectDTO(PROJECT, Collections.emptySet(), "", "", null,
                singletonList(new ProjectEndpointDTO("endpoint", UserInstanceStatus.RUNNING,
                        new EdgeInfo())), true);
    }
}
