package com.atlassian.stash.internal.plugin.hooks.allapprovers;

import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.bitbucket.i18n.SimpleI18nService;
import com.atlassian.bitbucket.pull.PullRequest;
import com.atlassian.bitbucket.pull.PullRequestParticipant;
import com.atlassian.bitbucket.pull.PullRequestRef;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.scm.pull.MergeRequest;
import com.google.common.collect.ImmutableSet;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;

import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class AllApproversMergeCheckTest {

    private AllApproversMergeCheck mergeCheck;
    @Mock
    private AllApproversMergeCheckConfig config;
    @Mock
    private MergeRequest mergeRequest;
    @Mock
    private PullRequest pullRequest;
    @Mock
    private PullRequestRef toRef;
    @Mock
    private Repository repository;
    @Spy
    private I18nService i18nService = new SimpleI18nService(SimpleI18nService.Mode.RETURN_KEYS);

    @Before
    public void setup() {
        when(mergeRequest.getPullRequest()).thenReturn(pullRequest);
        when(pullRequest.getToRef()).thenReturn(toRef);
        when(toRef.getRepository()).thenReturn(repository);

        mergeCheck = new AllApproversMergeCheck(config, i18nService);
    }

    @Test
    public void testCheckDoesNotVetoIfConfigPropertyIsFalse() {
        when(config.areAllApproversRequired(repository)).thenReturn(false);

        mergeCheck.check(mergeRequest);

        verify(mergeRequest, never()).veto(any(), any());
    }

    @Test
    public void testCheckDoesNotVetoIfNoReviewers() {
        when(config.areAllApproversRequired(repository)).thenReturn(true);
        when(pullRequest.getReviewers()).thenReturn(ImmutableSet.of());

        mergeCheck.check(mergeRequest);

        verify(mergeRequest, never()).veto(any(), any());
    }

    @Test
    public void testCheckDoesNotVetoIfAllReviewersHaveApproved() {
        when(config.areAllApproversRequired(repository)).thenReturn(true);
        PullRequestParticipant reviewer1 = mock(PullRequestParticipant.class);
        when(reviewer1.isApproved()).thenReturn(true);
        PullRequestParticipant reviewer2 = mock(PullRequestParticipant.class);
        when(reviewer2.isApproved()).thenReturn(true);
        when(pullRequest.getReviewers()).thenReturn(ImmutableSet.of(reviewer1, reviewer2));

        mergeCheck.check(mergeRequest);

        verify(mergeRequest, never()).veto(any(), any());
    }

    @Test
    public void testCheckDoesVetoIfNotAllReviewersHaveApproved() {
        when(config.areAllApproversRequired(repository)).thenReturn(true);
        PullRequestParticipant reviewer1 = mock(PullRequestParticipant.class);
        when(reviewer1.isApproved()).thenReturn(false);
        PullRequestParticipant reviewer2 = mock(PullRequestParticipant.class);
        when(reviewer2.isApproved()).thenReturn(true);
        when(pullRequest.getReviewers()).thenReturn(ImmutableSet.of(reviewer1, reviewer2));

        mergeCheck.check(mergeRequest);

        verify(mergeRequest).veto("bitbucket.pull.require.all.approvals.for.merge.label",
                "bitbucket.pull.require.all.approvals.for.merge.message");
    }
}