package com.braintree.configuration;

import de.hybris.bootstrap.annotations.UnitTest;
import de.hybris.platform.servicelayer.config.ConfigurationService;
import de.hybris.platform.servicelayer.config.impl.HybrisConfiguration;
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;

import java.util.Enumeration;

import static com.braintree.constants.BraintreeConstants.PropertyConfiguration.BRAINTREE_PRIVATE_KEY;
import static com.braintree.constants.BraintreeConstants.PropertyConfiguration.BRAINTREE_MERCHANT_ID;
import static com.braintree.constants.BraintreeConstants.PropertyConfiguration.BRAINTREE_PUBLIC_KEY;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;

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

    private static final String LOG_ALL_ENABLE = "braintree.log.all.enable";
    private static final String BRAINTREE_ENVIRONMENT = "braintree.environment.type";
    private static final String TRUE = "true";
    private static final String FALSE = "false";
    private static final String LOG_PACKAGE_PATH = "com.braintree";
    private static final String INCORRECT_LOG_PACKAGE_PATH = "com.some";

    @Mock
    private Enumeration<Logger> enumeration;
    @Mock
    private Logger logger;

    @Spy
    @InjectMocks
    private BrainTreeConfigurationListener unit;

    @Test
    public void shouldSetLogLevelAll() {
        try (MockedStatic<LogManager> logManagerMockedStatic = mockStatic(LogManager.class)) {
            logManagerMockedStatic.when(LogManager::getCurrentLoggers).thenReturn(enumeration);
            when(enumeration.hasMoreElements()).thenReturn(true, false);
            when(enumeration.nextElement()).thenReturn(logger);
            when(logger.getName()).thenReturn(LOG_PACKAGE_PATH);

            unit.configChanged(LOG_ALL_ENABLE, TRUE);

            verify(logger).setLevel(Level.ALL);
            verify(unit).setLogLevel(Level.ALL);
        }
    }

    @Test
    public void shouldNoSetLogLevelAllWhenIncorrectLogPath() {
        try (MockedStatic<LogManager> logManagerMockedStatic = mockStatic(LogManager.class)) {
            logManagerMockedStatic.when(LogManager::getCurrentLoggers).thenReturn(enumeration);
            when(enumeration.hasMoreElements()).thenReturn(true, false);
            when(enumeration.nextElement()).thenReturn(logger);
            when(logger.getName()).thenReturn(INCORRECT_LOG_PACKAGE_PATH);

            unit.configChanged(LOG_ALL_ENABLE, TRUE);

            verify(logger, never()).setLevel(Level.ALL);
            verify(unit).setLogLevel(Level.ALL);
        }
    }

    @Test
    public void shouldNoSetLogLevelAllWhenCurrentLoggersIsEmpty() {
        try (MockedStatic<LogManager> logManagerMockedStatic = mockStatic(LogManager.class)) {
            logManagerMockedStatic.when(LogManager::getCurrentLoggers).thenReturn(enumeration);
            when(enumeration.hasMoreElements()).thenReturn(false);

            unit.configChanged(LOG_ALL_ENABLE, TRUE);

            verify(logger, never()).setLevel(Level.ALL);
            verify(unit).setLogLevel(Level.ALL);
        }
    }

    @Test
    public void shouldSetLogLevelError() {
        doNothing().when(unit).setLogLevel(Level.ERROR);

        unit.configChanged(LOG_ALL_ENABLE, FALSE);

        verify(unit).setLogLevel(Level.ERROR);
    }

    @Test
    public void shouldCallClearMerchantGatewayAccountCredentials() {
        doNothing().when(unit).clearMerchantGatewayAccountCredentials();

        unit.configChanged(BRAINTREE_ENVIRONMENT, FALSE);

        verify(unit).clearMerchantGatewayAccountCredentials();
    }

    @Test
    public void shouldClearMerchantGatewayAccountCredentials() {
        ConfigurationService configurationService = mock(ConfigurationService.class);
        HybrisConfiguration hybrisConfiguration = mock(HybrisConfiguration.class);

        doReturn(configurationService).when(unit).getConfigurationService();
        doReturn(hybrisConfiguration).when(configurationService).getConfiguration();
        doNothing().when(hybrisConfiguration).setProperty(BRAINTREE_PRIVATE_KEY, "");
        doNothing().when(hybrisConfiguration).setProperty(BRAINTREE_MERCHANT_ID, "");
        doNothing().when(hybrisConfiguration).setProperty(BRAINTREE_PUBLIC_KEY, "");

        unit.clearMerchantGatewayAccountCredentials();

        verify(unit).getConfigurationService();
        verify(configurationService).getConfiguration();
        verify(configurationService).getConfiguration();
        verify(hybrisConfiguration).setProperty(BRAINTREE_PRIVATE_KEY, "");
        verify(hybrisConfiguration).setProperty(BRAINTREE_MERCHANT_ID, "");
        verify(hybrisConfiguration).setProperty(BRAINTREE_PUBLIC_KEY, "");
    }

}
