package com.atlassian.bitbucket.internal.mirroring.mirror.auth.http;

import com.atlassian.bitbucket.auth.HttpAuthenticationContext;
import com.atlassian.bitbucket.internal.mirroring.mirror.MirrorAuthenticationContext;
import com.atlassian.bitbucket.internal.mirroring.mirror.auth.MirrorLfsJwtAuthenticationHandler;
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 org.springframework.mock.web.MockHttpServletRequest;

import java.util.Optional;

import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class MirrorLfsJwtAuthenticationHandlerTest {

    @Mock
    private MirrorAuthenticationContext mirrorAuthenticationContext;

    @InjectMocks
    private MirrorLfsJwtAuthenticationHandler underTest;

    @Test
    public void authenticatesBatchRequestWithJwtToken() {
        HttpAuthenticationContext httpAuthenticationContext = mock(HttpAuthenticationContext.class);
        MockHttpServletRequest request = new MockHttpServletRequest("POST",
                "https://example.com/bitbucket/rfupstream/one/b.git/info/lfs/objects/batch");
        request.setPathInfo("/rfupstream/one/b.git/info/lfs/objects/batch");
        request.addHeader("Authorization", "JWT foobar");
        when(httpAuthenticationContext.getRequest()).thenReturn((request));
        when(mirrorAuthenticationContext.getImpersonatedUser()).thenReturn(Optional.of(mock(ApplicationUser.class)));

        underTest.authenticate(httpAuthenticationContext);

        verify(mirrorAuthenticationContext).getImpersonatedUser();
    }

    @Test
    public void authenticatesStorageRequest() {
        HttpAuthenticationContext httpAuthenticationContext = mock(HttpAuthenticationContext.class);
        MockHttpServletRequest request = new MockHttpServletRequest("POST",
                "https://example.com/bitbucket/bitbucket/rest/git-lfs/storage/ONE/b/abcd123");
        request.setServletPath("/rest/git-lfs/storage/ONE/b/abcd123");
        when(httpAuthenticationContext.getRequest()).thenReturn((request));
        when(mirrorAuthenticationContext.getImpersonatedUser()).thenReturn(Optional.of(mock(ApplicationUser.class)));

        underTest.authenticate(httpAuthenticationContext);

        verify(mirrorAuthenticationContext).getImpersonatedUser();
    }

    @Test
    public void ignoresBatchRequest() {
        HttpAuthenticationContext httpAuthenticationContext = mock(HttpAuthenticationContext.class);
        MockHttpServletRequest request = new MockHttpServletRequest("POST",
                "https://example.com/bitbucket/rfupstream/one/b.git/info/lfs/objects/batch");
        request.setPathInfo("/rfupstream/one/b.git/info/lfs/objects/batch");
        when(httpAuthenticationContext.getRequest()).thenReturn((request));
        when(mirrorAuthenticationContext.getImpersonatedUser()).thenReturn(Optional.of(mock(ApplicationUser.class)));

        assertNull(underTest.authenticate(httpAuthenticationContext));
        verifyZeroInteractions(mirrorAuthenticationContext);
    }

    @Test
    public void ignoresNonLfsRequest() {
        HttpAuthenticationContext httpAuthenticationContext = mock(HttpAuthenticationContext.class);
        MockHttpServletRequest request = new MockHttpServletRequest("GET",
                "https://example.com/bitbucket/scm/one/a.git");
        request.setServletPath("/scm/one/a.git");
        when(httpAuthenticationContext.getRequest()).thenReturn((request));
        when(mirrorAuthenticationContext.getImpersonatedUser()).thenReturn(Optional.of(mock(ApplicationUser.class)));

        assertNull(underTest.authenticate(httpAuthenticationContext));
        verifyZeroInteractions(mirrorAuthenticationContext);
    }
}