package com.braintree.actions.order;

import de.hybris.bootstrap.annotations.UnitTest;
import de.hybris.platform.core.enums.OrderStatus;
import de.hybris.platform.core.model.order.OrderModel;
import de.hybris.platform.orderhistory.model.OrderHistoryEntryModel;
import de.hybris.platform.orderprocessing.model.OrderProcessModel;
import de.hybris.platform.servicelayer.model.ModelService;
import de.hybris.platform.servicelayer.time.TimeService;
import de.hybris.platform.task.RetryLaterException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import java.util.List;
import java.util.Set;

import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

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

    private static final String OK = "OK";
    private static final String UNDEFINED = "UNDEFINED";
    private static final String NOK = "NOK";

    @Mock
    private ModelService mockModelService;
    @Mock
    private TimeService timeService;

    @InjectMocks
    private BrainTreeOrderManualCheckedAction action;

    private OrderHistoryEntryModel historyLog;

    @Before
    public void setUp() {
        historyLog = new OrderHistoryEntryModel();
        BDDMockito.given(mockModelService.create(OrderHistoryEntryModel.class)).willReturn(historyLog);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testOrderCheckedNullProcess() throws RetryLaterException, Exception {//NOSONAR
        action.execute(null);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testOrderCheckedNullOrder() throws RetryLaterException, Exception {//NOSONAR
        final OrderProcessModel process = new OrderProcessModel();
        action.execute(process);
    }

    @Test
    public void testOrderCheckedFraud() throws RetryLaterException, Exception {//NOSONAR

        final OrderProcessModel process = new OrderProcessModel();
        final OrderModel fraudOrder = new OrderModel();
        fraudOrder.setFraudulent(Boolean.TRUE);
        process.setOrder(fraudOrder);
        assertEquals(NOK, action.execute(process));
        BDDMockito.verify(mockModelService).save(historyLog);
        assertEquals(fraudOrder, historyLog.getOrder());
        assertEquals(OrderStatus.SUSPENDED, fraudOrder.getStatus());
    }

    @Test
    public void testOrderCheckedOK() throws RetryLaterException, Exception {

        final OrderProcessModel process = new OrderProcessModel();
        final OrderModel okOrder = new OrderModel();
        okOrder.setFraudulent(Boolean.FALSE);
        process.setOrder(okOrder);
        assertEquals(OK, action.execute(process));
        BDDMockito.verify(mockModelService).save(historyLog);
        assertEquals(okOrder, historyLog.getOrder());
    }

    @Test
    public void testOrderUndefined() throws RetryLaterException, Exception {

        final OrderProcessModel process = new OrderProcessModel();
        final OrderModel undefinedOrder = new OrderModel();
        process.setOrder(undefinedOrder);
        assertEquals(UNDEFINED, action.execute(process));
    }

    @Test
    public void shouldGetTransition() {
        //when
        Set<String> transitions = action.getTransitions();

        //then
        assertTrue(transitions.containsAll(List.of(OK, NOK, UNDEFINED)));
    }

}
