package com.atlassian.bitbucket.internal.jwt;

import com.atlassian.bitbucket.auth.AuthenticationContext;
import com.atlassian.bitbucket.permission.Permission;
import com.atlassian.bitbucket.permission.PermissionService;
import com.atlassian.bitbucket.user.ApplicationUser;
import com.atlassian.jwt.writer.JwtJsonBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import java.util.Map;

import static org.junit.Assert.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class UserDetailsJwtClaimWriterTest {
    @Mock
    private AuthenticationContext authenticationContext;
    @Mock
    private JwtJsonBuilder builder;
    @Mock
    private PermissionService permissionService;
    @Mock
    private ApplicationUser user;
    @InjectMocks
    private UserDetailsJwtClaimWriter writer;

    @Test
    public void testNotAuthenticated() {
        writer.write(builder);

        verify(builder, never()).claim(anyString(), any());
    }

    @Test
    public void testAuthenticated() {
        when(authenticationContext.getCurrentUser()).thenReturn(user);
        when(permissionService.getHighestGlobalPermission(user)).thenReturn(Permission.LICENSED_USER);
        when(user.getSlug()).thenReturn("user-slug");

        writer.write(builder);

        ArgumentCaptor<Map> captor = ArgumentCaptor.forClass(Map.class);
        verify(builder).claim(eq("context"), captor.capture());
        Map userMap = (Map) captor.getValue().get("user");
        assertNotNull(userMap);
        assertEquals("user-slug", userMap.get("slug"));
        assertEquals(Permission.LICENSED_USER.name(), userMap.get("highestPermission"));
        assertEquals(2, userMap.size());
    }

    @Test
    public void testAuthenticatedNoPermission() {
        when(authenticationContext.getCurrentUser()).thenReturn(user);
        when(user.getSlug()).thenReturn("user-slug");

        writer.write(builder);

        ArgumentCaptor<Map> captor = ArgumentCaptor.forClass(Map.class);
        verify(builder).claim(eq("context"), captor.capture());
        Map userMap = (Map) captor.getValue().get("user");
        assertNotNull(userMap);
        assertEquals("user-slug", userMap.get("slug"));
        assertEquals(1, userMap.size());
    }
}