package com.braintreeocc.filters;

import de.hybris.bootstrap.annotations.UnitTest;
import de.hybris.platform.basecommerce.model.site.BaseSiteModel;
import de.hybris.platform.commerceservices.enums.CustomerType;
import de.hybris.platform.commerceservices.order.CommerceCartService;
import de.hybris.platform.core.model.order.CartModel;
import de.hybris.platform.core.model.user.CustomerModel;
import de.hybris.platform.core.model.user.UserModel;
import de.hybris.platform.servicelayer.user.UserService;
import de.hybris.platform.site.BaseSiteService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

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

@UnitTest
@RunWith(MockitoJUnitRunner.class)
public class BraintreeGuestRoleFilterTest {

    private static final String CART_GUID = "cartGuid";
    public static final String TEST_CARD_GUID = "Test card guid";

    @Mock
    private CommerceCartService commerceCartService;
    @Mock
    private BaseSiteService baseSiteService;
    @Mock
    private UserService userService;
    @Mock
    private HttpServletRequest request;
    @Mock
    private HttpServletResponse response;
    @Mock
    private FilterChain filterChain;
    @Mock
    private UserModel userModel;
    @Mock
    private CartModel cartModel;
    @Mock
    private BaseSiteModel baseSiteModel;
    @Mock
    private CustomerModel customerModel;
    @Mock
    private CustomerType customerType;

    @InjectMocks
    private BraintreeGuestRoleFilter unit;

    @Test
    public void doFilterInternalTest() throws ServletException, IOException {
        when(request.getParameter(CART_GUID)).thenReturn(TEST_CARD_GUID);
        when(baseSiteService.getCurrentBaseSite()).thenReturn(baseSiteModel);
        when(commerceCartService.getCartForGuidAndSite(TEST_CARD_GUID, baseSiteModel)).thenReturn(cartModel);
        when(userService.getCurrentUser()).thenReturn(userModel);
        when(userService.isAnonymousUser(userModel)).thenReturn(true);
        when(cartModel.getUser()).thenReturn(customerModel);
        when(customerModel.getType()).thenReturn(CustomerType.GUEST);

        unit.doFilterInternal(request, response, filterChain);

        verify(userService).setCurrentUser(customerModel);
        verify(filterChain).doFilter(request, response);
    }

    @Test
    public void doFilterInternalTestWhenCartModelIsNull() throws ServletException, IOException {
        when(request.getParameter(CART_GUID)).thenReturn(TEST_CARD_GUID);
        when(baseSiteService.getCurrentBaseSite()).thenReturn(baseSiteModel);
        when(commerceCartService.getCartForGuidAndSite(TEST_CARD_GUID, baseSiteModel)).thenReturn(null);

        unit.doFilterInternal(request, response, filterChain);

        verify(userService, never()).setCurrentUser(customerModel);
        verify(filterChain).doFilter(request, response);
    }

    @Test
    public void doFilterInternalTestWhenCartGuidIsNull() throws ServletException, IOException {
        when(request.getParameter(CART_GUID)).thenReturn(null);

        unit.doFilterInternal(request, response, filterChain);

        verify(userService, never()).setCurrentUser(customerModel);
        verify(filterChain).doFilter(request, response);
    }

    @Test
    public void doFilterInternalTestWhenUserIsNotAnonymous() throws ServletException, IOException {
        when(request.getParameter(CART_GUID)).thenReturn(TEST_CARD_GUID);
        when(baseSiteService.getCurrentBaseSite()).thenReturn(baseSiteModel);
        when(commerceCartService.getCartForGuidAndSite(TEST_CARD_GUID, baseSiteModel)).thenReturn(cartModel);
        when(userService.getCurrentUser()).thenReturn(userModel);
        when(userService.isAnonymousUser(userModel)).thenReturn(false);

        unit.doFilterInternal(request, response, filterChain);

        verify(userService, never()).setCurrentUser(customerModel);
        verify(filterChain).doFilter(request, response);
    }

    @Test
    public void doFilterInternalTestWhenUserModelIsNull() throws ServletException, IOException {
        when(request.getParameter(CART_GUID)).thenReturn(TEST_CARD_GUID);
        when(baseSiteService.getCurrentBaseSite()).thenReturn(baseSiteModel);
        when(commerceCartService.getCartForGuidAndSite(TEST_CARD_GUID, baseSiteModel)).thenReturn(cartModel);
        when(userService.getCurrentUser()).thenReturn(userModel);
        when(userService.isAnonymousUser(userModel)).thenReturn(true);
        when(cartModel.getUser()).thenReturn(null);

        unit.doFilterInternal(request, response, filterChain);

        verify(userService, never()).setCurrentUser(customerModel);
        verify(filterChain).doFilter(request, response);
    }

    @Test
    public void doFilterInternalTestWhenCustomerModelIsNull() throws ServletException, IOException {
        when(request.getParameter(CART_GUID)).thenReturn(TEST_CARD_GUID);
        when(baseSiteService.getCurrentBaseSite()).thenReturn(baseSiteModel);
        when(commerceCartService.getCartForGuidAndSite(TEST_CARD_GUID, baseSiteModel)).thenReturn(cartModel);
        when(userService.getCurrentUser()).thenReturn(userModel);
        when(userService.isAnonymousUser(userModel)).thenReturn(true);
        when(cartModel.getUser()).thenReturn(null);

        unit.doFilterInternal(request, response, filterChain);

        verify(userService, never()).setCurrentUser(customerModel);
        verify(filterChain).doFilter(request, response);
    }

    @Test
    public void doFilterInternalTestWhenIsNotAGuestCart() throws ServletException, IOException {
        when(request.getParameter(CART_GUID)).thenReturn(TEST_CARD_GUID);
        when(baseSiteService.getCurrentBaseSite()).thenReturn(baseSiteModel);
        when(commerceCartService.getCartForGuidAndSite(TEST_CARD_GUID, baseSiteModel)).thenReturn(cartModel);
        when(userService.getCurrentUser()).thenReturn(userModel);
        when(userService.isAnonymousUser(userModel)).thenReturn(true);
        when(cartModel.getUser()).thenReturn(customerModel);
        when(customerModel.getType()).thenReturn(CustomerType.REGISTERED);

        unit.doFilterInternal(request, response, filterChain);

        verify(userService, never()).setCurrentUser(customerModel);
        verify(filterChain).doFilter(request, response);
    }

    @Test
    public void isGuestShouldReturnFalseWhenCustomerModelNull(){
         assertFalse(unit.isGuest(null));
    }
}
