package com.atlassian.stash.internal.web.startup;

import com.atlassian.johnson.spring.lifecycle.LifecycleState;
import com.atlassian.stash.internal.lifecycle.StartupManager;
import com.atlassian.bitbucket.util.Progress;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;

import javax.servlet.http.HttpServletResponse;

import java.net.URLEncoder;

import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class StartupServletTest {

    private LifecycleState currentState = LifecycleState.STARTED;

    private StartupServlet servlet = new StartupServlet() {
        @Override
        protected LifecycleState getCurrentState() {
            return currentState;
        }

        @Override
        protected StartupManager getStartupManager() {
            return startupManager;
        }
    };

    @Mock
    private StartupManager startupManager;

    @Test
    public void testGetJson() throws Exception {
        Progress progress = mockProgressState("progress-message", 42);
        when(startupManager.getProgress()).thenReturn(progress);
        MockHttpServletRequest request = new MockHttpServletRequest("GET", "/system/startup");
        request.addHeader("Accept", "application/json");
        MockHttpServletResponse response = new MockHttpServletResponse();

        servlet.service(request, response);

        assertEquals(response.getContentType(), "application/json;charset=UTF-8");
        assertThat(response.getContentAsString(), allOf(containsString("\"message\":\"progress-message"),
                containsString("\"percentage\":42"), containsString("\"state\":\"STARTED\"")));
        assertEquals(response.getStatus(), HttpServletResponse.SC_OK);
    }

    @Test
    public void testRedirectToDestinationPage() throws Exception {
        String redirectUrl = "/bitbucket/projects/PROJ/repos/repo";
        MockHttpServletRequest request = new MockHttpServletRequest("GET", "/system/startup");
        request.setContextPath("/bitbucket");
        request.setParameter("next", URLEncoder.encode(redirectUrl, "UTF-8"));
        MockHttpServletResponse response = new MockHttpServletResponse();

        servlet.service(request, response);

        assertEquals(response.getRedirectedUrl(), redirectUrl);
        assertEquals(response.getStatus(), HttpServletResponse.SC_MOVED_TEMPORARILY);
    }

    @Test
    public void testRedirectToDestinationPageWithQueryParameter() throws Exception {
        String redirectUrl = "/bitbucket/projects/TEST/repos/test/pull-requests?create";
        MockHttpServletRequest request = new MockHttpServletRequest("GET", "/system/startup");
        request.setContextPath("/bitbucket");
        request.setParameter("next", URLEncoder.encode(redirectUrl, "UTF-8"));
        MockHttpServletResponse response = new MockHttpServletResponse();

        servlet.service(request, response);

        assertEquals(response.getRedirectedUrl(), redirectUrl);
        assertEquals(response.getStatus(), HttpServletResponse.SC_MOVED_TEMPORARILY);
    }

    @Test
    public void testRedirectToDestinationPageWithoutNextParameter() throws Exception {
        MockHttpServletRequest request = new MockHttpServletRequest("GET", "/system/startup");
        request.setContextPath("/bitbucket");
        MockHttpServletResponse response = new MockHttpServletResponse();

        servlet.service(request, response);

        assertEquals(response.getRedirectedUrl(), "/bitbucket");
        assertEquals(response.getStatus(), HttpServletResponse.SC_MOVED_TEMPORARILY);
    }

    private static Progress mockProgressState(String message, int percentage) {
        Progress progress = mock(Progress.class);
        when(progress.getMessage()).thenReturn(message);
        when(progress.getPercentage()).thenReturn(percentage);
        return progress;
    }

}
