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.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.AccessToken;
import com.avaya.collaboration.authorization.client.AuthorizationClientHelper;
import com.avaya.collaboration.authorization.client.HttpResponseException;
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.http.HttpRequestHeaderAdder;

@RunWith(MockitoJUnitRunner.class)
public class AccessTokenHeaderFilterTest
{
    AccessTokenHeaderFilter 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
    AccessToken mockAccessToken;

    @Mock
    Logger mockLogger;

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

    @Test
    public void testDoFilterGetsCalledWithValidAuthCode() throws AuthorizationHelperException, HttpResponseException, IOException,
            ServletException
    {
        when(mockHttpServletRequest.getParameter(AUTH_CODE_GRANT_TYPE)).thenReturn("value");
        when(mockAccessTokenProvider.getAccessTokenForUser(any(HttpServletRequest.class))).thenReturn(mockAccessToken);
        when(mockAccessToken.getSubject()).thenReturn("subject");
        when(mockAccessToken.getExpiresIn()).thenReturn(32400);
        when(mockAccessToken.toString()).thenReturn("token");

        classToTest.doFilter(mockHttpServletRequest, mockHttpServletResponse, mockFilterChain);
        verify(mockFilterChain).doFilter(any(HttpRequestHeaderAdder.class), any(HttpServletResponse.class));
    }

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

        classToTest.doFilter(mockHttpServletRequest, mockHttpServletResponse, mockFilterChain);
        verify(mockHttpServletResponse).sendError(HttpServletResponse.SC_UNAUTHORIZED, "No authorization code");
    }

    @Test
    public void testErrorSentWhenAccessTokenRequestFailed() throws AuthorizationHelperException, HttpResponseException, IOException,
            ServletException
    {
        when(mockHttpServletRequest.getParameter(AUTH_CODE_GRANT_TYPE)).thenReturn("value");
        when(mockAccessTokenProvider.getAccessTokenForUser(any(HttpServletRequest.class))).thenThrow(
                new AuthorizationHelperException("Server error"));

        classToTest.doFilter(mockHttpServletRequest, mockHttpServletResponse, mockFilterChain);
        verifyZeroInteractions(mockFilterChain);
        verify(mockHttpServletResponse).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Server error");
    }

}
