package com.intrasoft.ermis.transit.cargoofficeofdestination.adapter.service;

import com.intrasoft.ermis.cargov1.messages.MessageTypes;
import com.intrasoft.ermis.common.bpmn.core.BpmnEngine;
import com.intrasoft.ermis.common.bpmn.core.CorrelateBpmnMessageCommand;
import com.intrasoft.ermis.transit.cargoofficeofdestination.core.port.ValidationCompletedEventHandlerService;
import com.intrasoft.ermis.transit.cargoofficeofdestination.core.service.DossierDataService;
import com.intrasoft.ermis.transit.cargoofficeofdestination.domain.Message;
import com.intrasoft.ermis.transit.cargoofficeofdestination.domain.enums.BpmnFlowVariablesEnum;
import com.intrasoft.ermis.transit.cargoofficeofdestination.domain.enums.BpmnGlobalMessageNamesEnum;
import com.intrasoft.ermis.transit.cargoofficeofdestination.domain.events.ValidationCompletedDomainEvent;
import com.intrasoft.ermis.transit.common.enums.MessageStatusEnum;
import com.intrasoft.ermis.transit.common.exceptions.NotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class ValidationCompletedEventHandlerServiceImpl implements ValidationCompletedEventHandlerService {

    private final BpmnEngine bpmnEngine;

    private final DossierDataService dossierDataService;

    @Override
    public void onValidationCompletedEvent(ValidationCompletedDomainEvent validationCompletedDomainEvent, String messageType, String mrn)
            throws NotFoundException {

        CorrelateBpmnMessageCommand correlateBpmnMessageCommand = null;

        if (MessageTypes.TB_015_C.value().equals(messageType)) {
            correlateBpmnMessageCommand = CorrelateBpmnMessageCommand
                    .builder()
                    .businessKey(validationCompletedDomainEvent.getMovementId())
                    .messageName(BpmnGlobalMessageNamesEnum.TB015_VALIDATION_RESULTS_MESSAGE.getValue())
                    .value(BpmnFlowVariablesEnum.TB015_VALIDATION_ERRORS_FOUND.getValue(), validationCompletedDomainEvent.isRejecting())
                    .build();
        } else if (MessageTypes.TB_007_C.value().equals(messageType)) {
            correlateBpmnMessageCommand = CorrelateBpmnMessageCommand
                    .builder()
                    .businessKey(validationCompletedDomainEvent.getMovementId())
                    .messageName(BpmnGlobalMessageNamesEnum.TB007_VALIDATION_RESULTS_MESSAGE.getValue())
                    .value(BpmnFlowVariablesEnum.TB007_VALIDATION_ERRORS_FOUND.getValue(), validationCompletedDomainEvent.isRejecting())
                    .build();
        }

        if (correlateBpmnMessageCommand != null) {

            updateMessageStatus(validationCompletedDomainEvent);
            bpmnEngine.correlateMessage(correlateBpmnMessageCommand);
        }
    }

    private void updateMessageStatus(ValidationCompletedDomainEvent validationCompletedDomainEvent) throws NotFoundException {
        Message message = dossierDataService.getMessageById(validationCompletedDomainEvent.getMessageId());
        if (message != null) {
            dossierDataService.updateMessageStatus(message.getId(),
                    validationCompletedDomainEvent.isRejecting() ? MessageStatusEnum.REJECTED.name() : MessageStatusEnum.ACCEPTED.name());
        } else {
            throw new NotFoundException("No message found with id: " + validationCompletedDomainEvent.getMessageId());
        }
    }
}

package com.intrasoft.ermis.transit.cargoofficeofdestination.test.service;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.intrasoft.ermis.common.bpmn.core.BpmnEngine;
import com.intrasoft.ermis.common.bpmn.core.CorrelateBpmnMessageCommand;
import com.intrasoft.ermis.transit.cargoofficeofdestination.adapter.service.ValidationCompletedEventHandlerServiceImpl;
import com.intrasoft.ermis.transit.cargoofficeofdestination.core.service.DossierDataService;
import com.intrasoft.ermis.transit.cargoofficeofdestination.domain.Message;
import com.intrasoft.ermis.transit.cargoofficeofdestination.domain.enums.BpmnFlowVariablesEnum;
import com.intrasoft.ermis.transit.cargoofficeofdestination.domain.enums.BpmnGlobalMessageNamesEnum;
import com.intrasoft.ermis.transit.cargoofficeofdestination.domain.events.ValidationCompletedDomainEvent;
import com.intrasoft.ermis.transit.common.enums.MessageStatusEnum;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class ValidationCompletedEventHandlerServiceUT {

    private static final String MOVEMENT_ID = "MOCK_MOVEMENT_ID";

    private static final String MESSAGE_ID = "MOCK_MESSAGE_ID";

    private static final String MRN = "MOCK_MRN";

    @Mock
    private BpmnEngine bpmnEngine;

    @Mock
    private DossierDataService dossierDataService;

    @InjectMocks
    private ValidationCompletedEventHandlerServiceImpl validationCompletedEventHandlerService;

    @Captor
    private ArgumentCaptor<CorrelateBpmnMessageCommand> commandArgumentCaptor;

    @ParameterizedTest
    @DisplayName("Test - On Validation Completed Event")
    @ValueSource(strings = {"TB007C", "TB015C", "UNEXPECTED"})
    void testOnValidationCompletedEvent(String messageType) {
        // Test data:
        Message mockMessage = Message.builder()
                                     .id(MESSAGE_ID)
                                     .messageType(messageType)
                                     .build();
        ValidationCompletedDomainEvent mockValidationCompletedDomainEvent = ValidationCompletedDomainEvent.builder()
                                                                                                          .movementId(MOVEMENT_ID)
                                                                                                          .messageId(MESSAGE_ID)
                                                                                                          .rejecting(false)
                                                                                                          .build();
        // Stubs:
        if (!"UNEXPECTED".equals(messageType)) {
            when(dossierDataService.getMessageById(MESSAGE_ID)).thenReturn(mockMessage);
        }
        // Call tested method:
        validationCompletedEventHandlerService.onValidationCompletedEvent(mockValidationCompletedDomainEvent, messageType, MRN);
        // Verifications & Assertions:
        if ("UNEXPECTED".equals(messageType)) {
            verify(dossierDataService, times(0)).getMessageById(anyString());
            verify(dossierDataService, times(0)).updateMessageStatus(anyString(), anyString());
            verify(bpmnEngine, times(0)).correlateMessage(any(CorrelateBpmnMessageCommand.class));
        } else {
            verify(dossierDataService, times(1)).getMessageById(MESSAGE_ID);
            verify(dossierDataService, times(1)).updateMessageStatus(MESSAGE_ID, MessageStatusEnum.ACCEPTED.name());
            verify(bpmnEngine, times(1)).correlateMessage(commandArgumentCaptor.capture());
            assertEquals(MOVEMENT_ID, commandArgumentCaptor.getValue().getBusinessKey());
            if ("TB007C".equals(messageType)) {
                assertEquals(BpmnGlobalMessageNamesEnum.TB007_VALIDATION_RESULTS_MESSAGE.getValue(), commandArgumentCaptor.getValue().getMessageName());
                assertNotNull(commandArgumentCaptor.getValue().getValues());
                assertEquals(false, commandArgumentCaptor.getValue().getValues().get(BpmnFlowVariablesEnum.TB007_VALIDATION_ERRORS_FOUND.getValue()));
            } else if ("TB015C".equals(messageType)) {
                assertEquals(BpmnGlobalMessageNamesEnum.TB015_VALIDATION_RESULTS_MESSAGE.getValue(), commandArgumentCaptor.getValue().getMessageName());
                assertNotNull(commandArgumentCaptor.getValue().getValues());
                assertEquals(false, commandArgumentCaptor.getValue().getValues().get(BpmnFlowVariablesEnum.TB015_VALIDATION_ERRORS_FOUND.getValue()));
            }
        }
    }
}
