package com.atlassian.stash.internal.notification.pull.handlers;

import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.bitbucket.i18n.SimpleI18nService;
import com.atlassian.bitbucket.notification.pull.PullRequestOpenedNotification;
import com.atlassian.bitbucket.pull.PullRequest;
import com.atlassian.bitbucket.pull.PullRequestParticipant;
import com.atlassian.bitbucket.pull.PullRequestRole;
import com.atlassian.bitbucket.user.ApplicationUser;
import com.atlassian.fugue.Iterables;
import com.atlassian.stash.internal.notification.handlers.BaseNotificationHandlerTest;
import com.atlassian.stash.internal.notification.handlers.NotificationMailer;
import com.atlassian.stash.internal.notification.mention.MentionHelper;
import com.atlassian.stash.internal.notification.usersettings.SendMode;
import com.google.common.collect.ImmutableSet;
import org.apache.commons.lang3.RandomStringUtils;
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 java.util.Collections;
import java.util.Map;
import java.util.Set;

import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class PullRequestOpenedNotificationHandlerTest extends BaseNotificationHandlerTest {

    @Spy
    private I18nService i18nService = new SimpleI18nService();
    @Mock
    private NotificationMailer mailer;
    @Mock
    private MentionHelper mentionHelper;
    @InjectMocks
    private PullRequestOpenedNotificationHandler notificationHandler;

    @Test
    public void testContextValues() {
        PullRequestOpenedNotification notification = mock(PullRequestOpenedNotification.class);
        PullRequestNotificationTestUtils.setupNotification(notification);

        Map<String, Object> context = notificationHandler.getContext(notification);

        PullRequestNotificationTestUtils.assertNotification(notification, context);
    }

    @Test
    public void testNotifiedUsers() {
        PullRequestOpenedNotification notification = mock(PullRequestOpenedNotification.class);
        PullRequestNotificationTestUtils.setupNotification(notification);
        PullRequestNotificationTestUtils.setupNotificationPullRequest(notification);

        String description = RandomStringUtils.random(256);
        ApplicationUser mention = mock(ApplicationUser.class, "mention");
        ApplicationUser reviewer = mock(ApplicationUser.class, "reviewer");

        PullRequestParticipant participant = mock(PullRequestParticipant.class);
        when(participant.getRole()).thenReturn(PullRequestRole.REVIEWER);
        when(participant.getUser()).thenReturn(reviewer);

        PullRequest pullRequest = notification.getPullRequest();
        when(pullRequest.getReviewers()).thenReturn(Collections.singleton(participant));
        when(pullRequest.getDescription()).thenReturn(description);

        // Return both the reviewer and another mentioned user, to verify that mentioned reviewers are
        // filtered out, preventing them from receiving two e-mails when the pull request is opened
        when(mentionHelper.findUsers(same(notification), eq(description)))
                .thenReturn(ImmutableSet.of(mention, reviewer));

        notificationHandler.handle(notification, Iterables.<ApplicationUser>emptyIterable());

        verifySend(notification, Collections.singleton(mention), getSendModes());
    }

    private Set<SendMode> getSendModes() {
        return ImmutableSet.of(SendMode.IMMEDIATE, SendMode.BATCHED);
    }
}
