package at.procon.dip.domain.document.service;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import at.procon.dip.domain.document.RepresentationType;
import at.procon.dip.domain.document.entity.Document;
import at.procon.dip.domain.document.entity.DocumentContent;
import at.procon.dip.domain.document.entity.DocumentTextRepresentation;
import at.procon.dip.domain.document.repository.DocumentTextRepresentationRepository;
import at.procon.dip.domain.document.service.command.AddDocumentTextRepresentationCommand;
import at.procon.dip.search.service.DocumentLexicalIndexService;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class DocumentRepresentationServiceTest {

    @Mock
    private DocumentService documentService;
    @Mock
    private DocumentContentService contentService;
    @Mock
    private DocumentTextRepresentationRepository representationRepository;
    @Mock
    private DocumentLexicalIndexService lexicalIndexService;

    private DocumentRepresentationService service;

    @BeforeEach
    void setUp() {
        service = new DocumentRepresentationService(documentService, contentService, representationRepository, lexicalIndexService);
    }

    @Test
    void shouldIndexLexicallyByDefault() {
        UUID documentId = UUID.randomUUID();
        UUID contentId = UUID.randomUUID();
        UUID representationId = UUID.randomUUID();
        when(documentService.getRequired(documentId)).thenReturn(Document.builder().id(documentId).build());
        when(contentService.getRequired(contentId)).thenReturn(DocumentContent.builder().id(contentId).build());
        when(representationRepository.saveAndFlush(any(DocumentTextRepresentation.class))).thenAnswer(inv -> {
            DocumentTextRepresentation representation = inv.getArgument(0);
            representation.setId(representationId);
            return representation;
        });

        service.addRepresentation(new AddDocumentTextRepresentationCommand(
                documentId,
                contentId,
                RepresentationType.SEMANTIC_TEXT,
                "test-builder",
                "en",
                null,
                null,
                null,
                null,
                true,
                "Hello world",
                false
        ));

        verify(lexicalIndexService).indexRepresentation(representationId);
    }

    @Test
    void shouldSkipImmediateLexicalIndexingWhenDeferred() {
        UUID documentId = UUID.randomUUID();
        UUID contentId = UUID.randomUUID();
        when(documentService.getRequired(documentId)).thenReturn(Document.builder().id(documentId).build());
        when(contentService.getRequired(contentId)).thenReturn(DocumentContent.builder().id(contentId).build());
        when(representationRepository.saveAndFlush(any(DocumentTextRepresentation.class))).thenAnswer(inv -> inv.getArgument(0));

        service.addRepresentation(new AddDocumentTextRepresentationCommand(
                documentId,
                contentId,
                RepresentationType.SEMANTIC_TEXT,
                "test-builder",
                "en",
                null,
                null,
                null,
                null,
                true,
                "Hello world",
                true
        ));

        verify(lexicalIndexService, never()).indexRepresentation(any());
    }
}
