package com.atlassian.stash.internal.web.repos.jobs;

import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.bitbucket.i18n.SimpleI18nService;
import com.atlassian.stash.internal.pull.rescope.InternalPullRequestRescopeService;
import com.atlassian.stash.internal.pull.rescope.RepositoryRescopeResult;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.repository.RepositoryService;
import com.atlassian.bitbucket.permission.Permission;
import com.atlassian.bitbucket.permission.PermissionService;
import com.google.common.collect.ImmutableList;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import java.util.ArrayList;

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class RepositoryJobControllerTest {

    private static final String PROJECT_KEY = "project";
    private static final String REPO_SLUG = "repository";

    @Spy
    private I18nService i18nService = new SimpleI18nService();
    @Mock
    private PermissionService permissionService;
    @Mock
    private InternalPullRequestRescopeService pullRequestRescopeService;
    @Mock
    private RepositoryService repositoryService;
    @InjectMocks
    private RepositoryJobController controller;

    private final Repository repository = mock(Repository.class);

    @Before
    public void setup() {
        when(repositoryService.getBySlug(PROJECT_KEY, REPO_SLUG)).thenReturn(repository);
        when(permissionService.hasRepositoryPermission(repository, Permission.REPO_ADMIN)).thenReturn(true);
    }

    @Test
    public void testRescopeAllPullRequests() {
        when(pullRequestRescopeService.rescope(any(Repository.class), eq(ImmutableList.<String>of())))
                .thenReturn(new RepositoryRescopeResult(1, 0));

        ResponseEntity<RestRescopeResult> response = controller.rescopePullRequests(PROJECT_KEY, REPO_SLUG,
                false, new RestRescopeRequest(ImmutableList.of()));

        assertResponse(response, HttpStatus.OK, 1, 0);
        verify(pullRequestRescopeService).rescope(repository, ImmutableList.<String>of());
    }

    @Test
    public void testRescopePullRequestsForBranch() {
        when(pullRequestRescopeService.rescope(any(Repository.class), eq(ImmutableList.of("foo"))))
                .thenReturn(new RepositoryRescopeResult(1, 0));

        ResponseEntity<RestRescopeResult> response = controller.rescopePullRequests(PROJECT_KEY, REPO_SLUG,
                false, new RestRescopeRequest(ImmutableList.of("foo")));

        assertResponse(response, HttpStatus.OK, 1, 0);
        verify(pullRequestRescopeService).rescope(repository, ImmutableList.of("foo"));
    }

    @Test
    public void testRescopePullRequestsError() {
        when(pullRequestRescopeService.rescope(any(Repository.class), eq(new ArrayList<>())))
                .thenReturn(new RepositoryRescopeResult(1, 2));

        ResponseEntity<RestRescopeResult> response = controller.rescopePullRequests(PROJECT_KEY, REPO_SLUG,
                false, new RestRescopeRequest(ImmutableList.of()));

        assertResponse(response, HttpStatus.INTERNAL_SERVER_ERROR, 1, 2);
        verify(pullRequestRescopeService).rescope(repository, new ArrayList<>());
    }

    private static void assertResponse(ResponseEntity<RestRescopeResult> response, HttpStatus status,
                                       int skippedCount, int errorCount) {
        assertEquals(status, response.getStatusCode());
        assertEquals(skippedCount, response.getBody().get("skippedCount"));
        assertEquals(errorCount, response.getBody().get("errorCount"));
    }
}
