package com.atlassian.stash.sal.api.auth;

import com.atlassian.sal.api.page.PageCapability;
import com.atlassian.sal.api.user.UserRole;
import com.atlassian.bitbucket.nav.NavBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import java.net.URI;
import java.util.EnumSet;

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class LoginUriProviderImplTest {

    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
    private NavBuilder navBuilder;

    @InjectMocks
    private LoginUriProviderImpl uriProvider;

    @Test
    public void testGetLoginUri() throws Exception {
        String resourceRequiringLogin = "http://localhost/secure/resource";
        String expectedLogin = "http://example.com?next=http://localhost/secure/resource";

        when(navBuilder.login().next(eq(resourceRequiringLogin)).buildAbsolute()).thenReturn(expectedLogin);

        assertEquals(uri(expectedLogin), uriProvider.getLoginUri(uri(resourceRequiringLogin)));
    }

    @Test
    public void testGetLoginUriWithIframeCapability() throws Exception {
        String resourceRequiringLogin = "http://localhost/secure/resource";
        String expectedLogin = "http://example.com/login/embedded?next=http://localhost/secure/resource";

        when(navBuilder.login().embedded().next(eq(resourceRequiringLogin)).buildAbsolute()).thenReturn(expectedLogin);

        assertEquals(uri(expectedLogin), uriProvider.getLoginUri(uri(resourceRequiringLogin),
                EnumSet.of(PageCapability.IFRAME)));
    }

    @Test
    public void testGetLoginUriForSysadmin() throws Exception {
        String resourceRequiringLogin = "http://localhost/secure/resource";
        String expectedLogin = "http://example.com/login?next=http://localhost/secure/resource&permission=sysadmin";

        when(navBuilder.login().sysadmin().next(eq(resourceRequiringLogin)).buildAbsolute()).thenReturn(expectedLogin);

        assertEquals(uri(expectedLogin), uriProvider.getLoginUriForRole(uri(resourceRequiringLogin), UserRole.SYSADMIN));
    }

    @Test
    public void testGetLoginUriForAdmin() throws Exception {
        String resourceRequiringLogin = "http://localhost/secure/resource";
        String expectedLogin = "http://example.com/login?next=http://localhost/secure/resource&permission=admin";

        when(navBuilder.login().admin().next(eq(resourceRequiringLogin)).buildAbsolute()).thenReturn(expectedLogin);

        assertEquals(uri(expectedLogin), uriProvider.getLoginUriForRole(uri(resourceRequiringLogin), UserRole.ADMIN));
    }

    @Test
    public void testGetLoginUriForUser() throws Exception {
        String resourceRequiringLogin = "http://localhost/secure/resource";
        String expectedLogin = "http://example.com/login?next=http://localhost/secure/resource";

        // same as standard login, no extra params
        when(navBuilder.login().next(eq(resourceRequiringLogin)).buildAbsolute()).thenReturn(expectedLogin);

        assertEquals(uri(expectedLogin), uriProvider.getLoginUriForRole(uri(resourceRequiringLogin), UserRole.USER));
    }

    @Test
    public void testGetLoginUriForSysadminWithIframeCapability() throws Exception {
        String resourceRequiringLogin = "http://localhost/secure/resource";
        String expectedLogin = "http://example.com/login/embedded?next=http://localhost/secure/resource&permission=sysadmin";

        when(navBuilder.login().embedded().sysadmin().next(eq(resourceRequiringLogin)).buildAbsolute())
                .thenReturn(expectedLogin);

        assertEquals(uri(expectedLogin), uriProvider.getLoginUriForRole(uri(resourceRequiringLogin), UserRole.SYSADMIN,
                EnumSet.of(PageCapability.IFRAME)));
    }

    private static URI uri(String url) {
        return URI.create(url);
    }
}
