package com.avaya.zephyr.services.sample_services.Authorization;

import static org.mockito.Matchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import com.avaya.collaboration.authorization.AuthorizationHelperException;
import com.avaya.collaboration.authorization.client.AuthorizationClientHelper;
import com.avaya.collaboration.authorization.spi.AccessTokenProvider;
import com.avaya.collaboration.util.logger.Logger;
import com.avaya.zephyr.common.testutils.deencapsulation.Deencapsulation;
import com.avaya.zephyr.services.sample_services.Authorization.util.ServiceAttributeStore;

@RunWith(MockitoJUnitRunner.class)
public class AuthorizationCodeFilterTest
{
    AuthorizationCodeFilter classToTest;
    private static final String AUTH_CODE_GRANT_TYPE = "code";

    @Mock
    HttpServletRequest mockHttpServletRequest;

    @Mock
    HttpServletResponse mockHttpServletResponse;

    @Mock
    FilterChain mockFilterChain;

    @Mock
    FilterConfig mockFilterConfig;

    @Mock
    AccessTokenProvider mockAccessTokenProvider;

    @Mock
    Logger mockLogger;

    static Cookie[] requestCookies;
    static Cookie sessionCookie;

    @Before
    public void before()
    {
        classToTest = new AuthorizationCodeFilter(mockLogger);
        Deencapsulation.setField(AuthorizationClientHelper.class, "tokenProvider", mockAccessTokenProvider);
    }

    @Test
    public void testDoFilterGetsCalledWhenRequestContainsCookie() throws IOException, ServletException
    {
        sessionCookie = new Cookie("UserSession", "value");
        requestCookies = new Cookie[1];
        requestCookies[0] = sessionCookie;

        when(mockHttpServletRequest.getCookies()).thenReturn(requestCookies);
        ServiceAttributeStore.getInstance().setSessionCookieName("UserSession");

        classToTest.doFilter(mockHttpServletRequest, mockHttpServletResponse, mockFilterChain);
        verify(mockFilterChain).doFilter(mockHttpServletRequest, mockHttpServletResponse);
    }

    @Test
    public void testDoFilterGetsCalledWhenRequestContainsAuthCode() throws IOException, ServletException
    {
        when(mockHttpServletRequest.getParameter(AUTH_CODE_GRANT_TYPE)).thenReturn("value");

        classToTest.doFilter(mockHttpServletRequest, mockHttpServletResponse, mockFilterChain);
        verify(mockFilterChain).doFilter(mockHttpServletRequest, mockHttpServletResponse);
    }

    @Test
    public void testRequestIsRedirectedWhenNotContainsAuthCode() throws IOException, ServletException, AuthorizationHelperException
    {
        when(mockHttpServletRequest.getParameter(AUTH_CODE_GRANT_TYPE)).thenReturn("");
        when(mockAccessTokenProvider.getAuthorizationEndpoint(any(HttpServletRequest.class))).thenReturn("redirectURI");

        classToTest.doFilter(mockHttpServletRequest, mockHttpServletResponse, mockFilterChain);

        verify(mockAccessTokenProvider).getAuthorizationEndpoint(mockHttpServletRequest);
        verifyZeroInteractions(mockFilterChain);
        verify(mockHttpServletResponse).sendRedirect("redirectURI");
    }

    @Test
    public void testVerifyErrorSentWhenRedirectUriBuildThrowsError() throws AuthorizationHelperException, IOException, ServletException
    {
        when(mockHttpServletRequest.getParameter(AUTH_CODE_GRANT_TYPE)).thenReturn("");
        when(mockAccessTokenProvider.getAuthorizationEndpoint(any(HttpServletRequest.class))).thenThrow(
                new AuthorizationHelperException("URI build failed"));

        classToTest.doFilter(mockHttpServletRequest, mockHttpServletResponse, mockFilterChain);

        verifyZeroInteractions(mockFilterChain);
        verify(mockHttpServletResponse).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "URI build failed");
    }
}
