package com.atlassian.bitbucket.internal.mirroring.upstream;

import com.atlassian.bitbucket.event.user.UserCleanupEvent;
import com.atlassian.bitbucket.user.*;
import com.atlassian.event.api.EventPublisher;
import org.junit.Before;
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 static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;

@RunWith(MockitoJUnitRunner.class)
public class DefaultAddonUserHelperTest {
    @Mock
    private ServiceUser addonUser;
    @Mock
    private ApplicationUser normalUser;
    @Mock
    private ServiceUser upstreamUser;
    @Mock
    private EventPublisher eventPublisher;
    @Mock
    private UserAdminService userAdminService;
    @Mock
    private UserService userService;
    @InjectMocks
    private DefaultAddonUserHelper helper;

    @Before
    public void setUp() {
        when(addonUser.getType()).thenReturn(UserType.SERVICE);
        when(addonUser.getName()).thenReturn(DefaultAddonUserHelper.PREFIX_ADD_ON_USERNAME + "1234");
        when(normalUser.getType()).thenReturn(UserType.NORMAL);
        when(normalUser.getName()).thenReturn("username");
        when(upstreamUser.getType()).thenReturn(UserType.SERVICE);
        when(upstreamUser.getName()).thenReturn("upstream_abcd");
    }

    @Test
    public void testAddonUserIsDetected() throws Exception {
        assertTrue(DefaultAddonUserHelper.isAddonUser(addonUser));
        assertFalse(DefaultAddonUserHelper.isAddonUser(upstreamUser));
        assertFalse(DefaultAddonUserHelper.isAddonUser(normalUser));
    }

    @Test
    public void testAddonUsernameIsDetected() throws Exception {
        assertFalse(DefaultAddonUserHelper.isAddonUsername("upstream_1234"));
        assertTrue(DefaultAddonUserHelper.isAddonUsername("addon_1234"));
        assertFalse(DefaultAddonUserHelper.isAddonUsername(""));
        assertFalse(DefaultAddonUserHelper.isAddonUsername("1234_addon"));
    }

    @Test
    public void testGetUsernameForAddon() throws Exception {
        assertEquals("addon_1234", DefaultAddonUserHelper.getAddonUsernameFor("1234"));
    }

    @Test
    public void testGetAddonKeyFromUsername() throws Exception {
        assertEquals("1234", DefaultAddonUserHelper.getAddonKeyFromUsername("addon_1234"));
        assertEquals("", DefaultAddonUserHelper.getAddonKeyFromUsername("addon_"));
        assertNull(DefaultAddonUserHelper.getAddonKeyFromUsername("upstream_1234"));
        assertNull(DefaultAddonUserHelper.getAddonKeyFromUsername("normaluser"));
    }

    @Test
    public void testCleanupAddonUserNoMatch() {
        helper.cleanupAddonUser("doesnotexist");

        verifyZeroInteractions(userAdminService, eventPublisher);
    }

    @Test
    public void testCleanupAddonUserAlreadyDisabled() {
        String username  = DefaultAddonUserHelper.getAddonUsernameFor("addon");
        when(userService.getServiceUserByName(username, true)).thenReturn(addonUser);
        when(addonUser.isActive()).thenReturn(false);

        helper.cleanupAddonUser("addon");

        verifyZeroInteractions(userAdminService);
        verify(eventPublisher).publish(any(UserCleanupEvent.class));
    }

    @Test
    public void testCleanupAddonUser() {
        String username  = DefaultAddonUserHelper.getAddonUsernameFor("addon");
        when(userService.getServiceUserByName(username, true)).thenReturn(addonUser);
        when(addonUser.isActive()).thenReturn(true);

        helper.cleanupAddonUser("addon");

        ArgumentCaptor<ServiceUserUpdateRequest> requestCaptor = ArgumentCaptor.forClass(ServiceUserUpdateRequest.class);
        verify(userAdminService).updateServiceUser(requestCaptor.capture());
        assertFalse(requestCaptor.getValue().isActive());
        verify(eventPublisher).publish(any(UserCleanupEvent.class));

    }

}