package com.atlassian.stash.internal.auth;

import com.atlassian.plugin.PluginAccessor;
import com.atlassian.bitbucket.auth.HttpAuthenticationContext;
import com.atlassian.bitbucket.auth.HttpAuthenticationHandler;
import com.atlassian.bitbucket.auth.HttpAuthenticationHandlerModuleDescriptor;
import com.atlassian.bitbucket.plugin.ModuleDescriptorTestUtils;
import com.atlassian.bitbucket.user.ApplicationUser;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static org.junit.Assert.*;
import static org.mockito.Matchers.same;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class PluginHttpAuthenticationHandlerTest {
    
    @Mock
    HttpAuthenticationContext context;
    @Mock
    PluginAccessor pluginAccessor;
    @Mock
    HttpAuthenticationHandler handler1;
    @Mock
    HttpAuthenticationHandler handler2;
    @Mock
    ApplicationUser user;
    @InjectMocks
    PluginHttpAuthenticationHandler handler;

    @Test
    public void testAuthenticateNoModulesReturnsUser() throws Exception {
        // mock without modules
        mockPluginAccessor();

        assertNull(handler.authenticate(context));
    }

    @Test
    public void testAuthenticateAllModulesConsidered() throws Exception {
        mockPluginAccessor(handler1, handler2);

        assertNull(handler.authenticate(context));
        verify(handler1).authenticate(same(context));
        verify(handler2).authenticate(same(context));
    }

    @Test
    public void testAuthenticateProcessingStopsOnFirstModule() throws Exception {
        mockPluginAccessor(handler1, handler2);
        when(handler1.authenticate(same(context))).thenReturn(user);

        assertSame(user, handler.authenticate(context));
        verify(handler1).authenticate(same(context));
        verify(handler2, never()).authenticate(same(context));
    }

    @Test
    public void testRequiresAuthAllModulesConsidered() throws Exception {
        mockPluginAccessor(handler1, handler2);

        handler.validateAuthentication(context);

        verify(handler1).validateAuthentication(same(context));
        verify(handler2).validateAuthentication(same(context));
    }

    private void mockPluginAccessor(HttpAuthenticationHandler... handlers) {
        ModuleDescriptorTestUtils.mockWeightedModuleDescriptors(
                pluginAccessor, HttpAuthenticationHandlerModuleDescriptor.class, handlers);
    }

}
