package com.braintree.customersupportbackoffice.renderers;

import com.braintree.configuration.service.BrainTreeConfigService;
import com.braintree.enums.BraintreePayPalColor;
import com.braintree.enums.BraintreePayPalLabel;
import com.braintree.enums.BraintreePayPalLayout;
import com.braintree.enums.BraintreePayPalShape;
import com.braintree.method.BrainTreePaymentService;
import com.hybris.cockpitng.core.config.impl.jaxb.editorarea.AbstractPanel;
import com.hybris.cockpitng.core.model.ModelObserver;
import com.hybris.cockpitng.core.model.WidgetModel;
import com.hybris.cockpitng.dataaccess.facades.type.DataType;
import com.hybris.cockpitng.engine.WidgetInstanceManager;
import de.hybris.bootstrap.annotations.UnitTest;
import de.hybris.platform.basecommerce.model.site.BaseSiteModel;
import de.hybris.platform.core.model.BraintreePayPalConfigurationModel;
import de.hybris.platform.core.model.BraintreePayPalStylesConfigurationModel;
import de.hybris.platform.servicelayer.session.SessionService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;
import org.zkoss.zk.ui.Component;
import org.zkoss.zul.Div;
import org.zkoss.zul.Html;
import org.zkoss.zul.Iframe;
import org.zkoss.zul.Script;

import java.util.List;
import java.util.Optional;

import static com.hybris.backoffice.workflow.designer.handler.WorkflowDesignerCloseListener.VALUE_CHANGED;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

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

    private static final int BUTTON_HEIGHT = 35;
    private static final String ID = "id";
    private static final String CURRENT_OBJECT_DOTLESS = "currentObject";
    private static final String SCRIPT_CONTENT = "setTimeout(renderPayPalButton, 1000)";
    private static final String HTML_CONTENT_TAGLINE_FALSE = "<script> function renderPayPalButton() {$('.paypal-preview-button-iframe').contents().find('body').append(\"<script>function loadScript(src) {return new Promise(function(resolve, reject) {const script = document.createElement('script');script.type = 'text/javascript';script.src = src;script.async = true;script.onerror = function(err) {reject(err, script); };script.onload = script.onreadystatechange = function() {if (!this.readyState || this.readyState == 'complete') {resolve(); } };document.body.appendChild(script);}); }loadScript('https://js.braintreegateway.com/web/3.97.1/js/client.min.js').then((data) => {loadScript('https://js.braintreegateway.com/web/3.97.1/js/paypal-checkout.min.js')}).then((data) => { braintree.client.create({  authorization: 'null'}).then(function (clientInstance) {   return braintree.paypalCheckout.create({    client: clientInstance  });}).then(function (paypalCheckoutInstance) { paypalCheckoutInstance.loadPayPalSDK().then(function () {  var div = document.createElement('div');div.id = 'paypal-button-cnt'; if (window.self !== window.top) {document.body.appendChild(div);} else {document.getElementsByClassName('paypal-preview-button-iframe')[0].contentDocument.getElementsByTagName('body')[0].appendChild(div);}paypal.Buttons({style: {disableMaxWidth: true, layout: 'vertical', color: 'black', shape: 'pill', label: 'checkout', height: 35, tagline: false }, fundingSource: paypal.FUNDING.PAYPAL}).render(div); });}).catch(function (err) { console.log(err) });});<\\/script>\")} </script>";
    private static final String HTML_CONTENT_TAGLINE_TRUE = "<script> function renderPayPalButton() {$('.paypal-preview-button-iframe').contents().find('body').append(\"<script>function loadScript(src) {return new Promise(function(resolve, reject) {const script = document.createElement('script');script.type = 'text/javascript';script.src = src;script.async = true;script.onerror = function(err) {reject(err, script); };script.onload = script.onreadystatechange = function() {if (!this.readyState || this.readyState == 'complete') {resolve(); } };document.body.appendChild(script);}); }loadScript('https://js.braintreegateway.com/web/3.97.1/js/client.min.js').then((data) => {loadScript('https://js.braintreegateway.com/web/3.97.1/js/paypal-checkout.min.js')}).then((data) => { braintree.client.create({  authorization: 'null'}).then(function (clientInstance) {   return braintree.paypalCheckout.create({    client: clientInstance  });}).then(function (paypalCheckoutInstance) { paypalCheckoutInstance.loadPayPalSDK().then(function () {  var div = document.createElement('div');div.id = 'paypal-button-cnt'; if (window.self !== window.top) {document.body.appendChild(div);} else {document.getElementsByClassName('paypal-preview-button-iframe')[0].contentDocument.getElementsByTagName('body')[0].appendChild(div);}paypal.Buttons({style: {disableMaxWidth: true, layout: 'horizontal', color: 'black', shape: 'pill', label: 'checkout', height: 35, tagline: true }, fundingSource: paypal.FUNDING.PAYPAL}).render(div); });}).catch(function (err) { console.log(err) });});<\\/script>\")} </script>";


    @Mock
    private BrainTreeConfigService brainTreeConfigService;
    @Mock
    private SessionService sessionService;
    @Mock
    private BrainTreePaymentService brainTreePaymentService;

    @Spy
    @InjectMocks
    private PaypalPreviewButtonRenderer unit;

    @Mock
    private Component component;
    @Mock
    private AbstractPanel abstractPanel;
    @Mock
    private BraintreePayPalStylesConfigurationModel stylesConfiguration;
    @Mock
    private BraintreePayPalConfigurationModel payPalConfigurationModel;
    @Mock
    private DataType dataType;
    @Mock
    private WidgetInstanceManager widgetInstanceManager;
    @Mock
    private WidgetModel widgetModel;
    @Mock
    private Iframe iframe;
    @Mock
    private Script script;
    @Mock
    private Html html;
    @Mock
    private Div div;
    @Mock
    private BaseSiteModel baseSite;

    @Captor
    private ArgumentCaptor<ModelObserver> modelObserverArgumentCaptor;

    @Test
    public void shouldRenderPayPalButtonWithTaglineFalse() {
        doReturn(iframe).when(unit).createIframe();
        doReturn(script).when(unit).createScript();
        doReturn(html).when(unit).createHtml(any());
        doReturn(div).when(unit).createDiv();

        when(widgetInstanceManager.getModel()).thenReturn(widgetModel);
        when(payPalConfigurationModel.getBraintreePayPalConfigurationId()).thenReturn(ID);
        when(stylesConfiguration.getBraintreePayPalConfiguration()).thenReturn(payPalConfigurationModel);
        when(stylesConfiguration.getLayout()).thenReturn(BraintreePayPalLayout.VERTICAL);
        when(stylesConfiguration.getColor()).thenReturn(BraintreePayPalColor.BLACK);
        when(stylesConfiguration.getShape()).thenReturn(BraintreePayPalShape.PILL);
        when(stylesConfiguration.getLabel()).thenReturn(BraintreePayPalLabel.CHECKOUT);
        when(stylesConfiguration.getHeight()).thenReturn(BUTTON_HEIGHT);

        when(brainTreeConfigService.getBaseSiteForPayPalConfigurationId(ID)).thenReturn(Optional.of(baseSite));

        unit.render(component, abstractPanel, stylesConfiguration, dataType, widgetInstanceManager);

        verify(script).setContent(SCRIPT_CONTENT);
        verify(unit).createHtml(HTML_CONTENT_TAGLINE_FALSE);
    }

    @Test
    public void shouldNotRenderPayPalButtonWithWithCurrentRootNull() {
        doReturn(iframe).when(unit).createIframe();
        doReturn(script).when(unit).createScript();
        doReturn(html).when(unit).createHtml(any());
        doReturn(div).when(unit).createDiv();

        when(widgetInstanceManager.getModel()).thenReturn(widgetModel);
        when(widgetModel.getValue(CURRENT_OBJECT_DOTLESS, BraintreePayPalStylesConfigurationModel.class)).thenReturn(null);

        when(payPalConfigurationModel.getBraintreePayPalConfigurationId()).thenReturn(ID);
        when(stylesConfiguration.getBraintreePayPalConfiguration()).thenReturn(payPalConfigurationModel);
        when(stylesConfiguration.getLayout()).thenReturn(BraintreePayPalLayout.HORIZONTAL);
        when(stylesConfiguration.getColor()).thenReturn(BraintreePayPalColor.BLACK);
        when(stylesConfiguration.getShape()).thenReturn(BraintreePayPalShape.PILL);
        when(stylesConfiguration.getLabel()).thenReturn(BraintreePayPalLabel.CHECKOUT);
        when(stylesConfiguration.getHeight()).thenReturn(BUTTON_HEIGHT);
        when(stylesConfiguration.isTagline()).thenReturn(true);
        when(brainTreeConfigService.getBaseSiteForPayPalConfigurationId(ID)).thenReturn(Optional.of(baseSite));

        unit.render(component, abstractPanel, stylesConfiguration, dataType, widgetInstanceManager);

        verify(widgetModel).addObserver(eq(VALUE_CHANGED), modelObserverArgumentCaptor.capture());
        ModelObserver value = modelObserverArgumentCaptor.getValue();
        value.modelChanged();
    }

    @Test
    public void shouldRenderPayPalButtonWithTaglineTrue() {
        doReturn(iframe).when(unit).createIframe();
        doReturn(script).when(unit).createScript();
        doReturn(html).when(unit).createHtml(any());
        doReturn(div).when(unit).createDiv();

        when(widgetInstanceManager.getModel()).thenReturn(widgetModel);
        when(payPalConfigurationModel.getBraintreePayPalConfigurationId()).thenReturn(ID);
        when(stylesConfiguration.getBraintreePayPalConfiguration()).thenReturn(payPalConfigurationModel);
        when(stylesConfiguration.getLayout()).thenReturn(BraintreePayPalLayout.HORIZONTAL);
        when(stylesConfiguration.getColor()).thenReturn(BraintreePayPalColor.BLACK);
        when(stylesConfiguration.getShape()).thenReturn(BraintreePayPalShape.PILL);
        when(stylesConfiguration.getLabel()).thenReturn(BraintreePayPalLabel.CHECKOUT);
        when(stylesConfiguration.getHeight()).thenReturn(BUTTON_HEIGHT);
        when(stylesConfiguration.isTagline()).thenReturn(true);

        when(brainTreeConfigService.getBaseSiteForPayPalConfigurationId(ID)).thenReturn(Optional.of(baseSite));

        unit.render(component, abstractPanel, stylesConfiguration, dataType, widgetInstanceManager);

        verify(script).setContent(SCRIPT_CONTENT);
        verify(unit).createHtml(HTML_CONTENT_TAGLINE_TRUE);
    }

    @Test
    public void shouldAddObserver() {
        List<Component> childrenComponents = mock(List.class);
        doReturn(iframe).when(unit).createIframe();
        doReturn(script).when(unit).createScript();
        doReturn(html).when(unit).createHtml(any());
        doReturn(div).when(unit).createDiv();

        when(widgetInstanceManager.getModel()).thenReturn(widgetModel);
        when(widgetModel.getValue(CURRENT_OBJECT_DOTLESS, BraintreePayPalStylesConfigurationModel.class)).thenReturn(stylesConfiguration);

        when(payPalConfigurationModel.getBraintreePayPalConfigurationId()).thenReturn(ID);
        when(stylesConfiguration.getBraintreePayPalConfiguration()).thenReturn(payPalConfigurationModel);
        when(stylesConfiguration.getLayout()).thenReturn(BraintreePayPalLayout.HORIZONTAL);
        when(stylesConfiguration.getColor()).thenReturn(BraintreePayPalColor.BLACK);
        when(stylesConfiguration.getShape()).thenReturn(BraintreePayPalShape.PILL);
        when(stylesConfiguration.getLabel()).thenReturn(BraintreePayPalLabel.CHECKOUT);
        when(stylesConfiguration.getHeight()).thenReturn(BUTTON_HEIGHT);
        when(stylesConfiguration.isTagline()).thenReturn(true);
        when(brainTreeConfigService.getBaseSiteForPayPalConfigurationId(ID)).thenReturn(Optional.of(baseSite));
        when(component.getChildren()).thenReturn(childrenComponents);

        unit.render(component, abstractPanel, stylesConfiguration, dataType, widgetInstanceManager);

        verify(widgetModel).addObserver(eq(VALUE_CHANGED), modelObserverArgumentCaptor.capture());
        ModelObserver value = modelObserverArgumentCaptor.getValue();
        value.modelChanged();
        verify(childrenComponents).clear();
    }

}