package com.braintree.jobs;

import com.braintree.constants.BraintreefulfilmentprocessConstants;
import de.hybris.bootstrap.annotations.UnitTest;
import de.hybris.platform.cronjob.enums.CronJobResult;
import de.hybris.platform.cronjob.enums.CronJobStatus;
import de.hybris.platform.cronjob.model.CronJobModel;
import de.hybris.platform.processengine.BusinessProcessService;
import de.hybris.platform.processengine.model.BusinessProcessModel;
import de.hybris.platform.servicelayer.cronjob.PerformResult;
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
import de.hybris.platform.servicelayer.search.FlexibleSearchService;
import de.hybris.platform.servicelayer.search.SearchResult;
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.runners.MockitoJUnitRunner;

import java.util.List;
import java.util.Map;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

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

    private static final String PROCESS_DEFINITION_NAME = "processDefinitionName";
    private static final String PROCESS_CURRENT_ACTION = "processCurrentAction";
    private static final String WAIT_FOR_CLEAN_UP = "waitForCleanUp";
    private static final String CODE = "CODE";
    private static final String CODE_CLEAN_UP_EVENT = "CODE_CleanUpEvent";
    private String QUERY = "select {bp.PK} " + "from {BusinessProcess AS bp  JOIN ProcessTask AS pt ON {bp.pk} = {pt.process} } "
            + "WHERE {bp.processDefinitionName} = ?processDefinitionName and {pt.action} = ?processCurrentAction";

    @Mock
    private BusinessProcessService businessProcessService;
    @Mock
    private FlexibleSearchService flexibleSearchService;

    @InjectMocks
    private BrainTreeCleanUpFraudOrderJob unit;

    @Mock
    private CronJobModel cronJob;
    @Mock
    private SearchResult searchResult;
    @Mock
    private BusinessProcessModel process;

    @Captor
    private ArgumentCaptor<FlexibleSearchQuery> flexibleSearchQueryArgumentCaptor;

    @Test
    public void shouldPerform() {
        //given
        when(flexibleSearchService.search(any(FlexibleSearchQuery.class))).thenReturn(searchResult);
        when(searchResult.getResult()).thenReturn(List.of(process));
        when(process.getCode()).thenReturn(CODE);

        //when
        PerformResult result = unit.perform(cronJob);

        //then
        assertNotNull(result);
        assertEquals(CronJobResult.SUCCESS, result.getResult());
        assertEquals(CronJobStatus.FINISHED, result.getStatus());


        verify(flexibleSearchService).search(flexibleSearchQueryArgumentCaptor.capture());
        Map<String, Object> queryParameters = flexibleSearchQueryArgumentCaptor.getValue().getQueryParameters();
        assertEquals(BraintreefulfilmentprocessConstants.ORDER_PROCESS_NAME, queryParameters.get(PROCESS_DEFINITION_NAME));
        assertEquals(WAIT_FOR_CLEAN_UP, queryParameters.get(PROCESS_CURRENT_ACTION));
        assertEquals(QUERY, flexibleSearchQueryArgumentCaptor.getValue().getQuery());

        verify(businessProcessService).triggerEvent(CODE_CLEAN_UP_EVENT);
    }

}
