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

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;

import at.procon.dip.domain.access.DocumentVisibility;
import at.procon.dip.domain.document.DocumentAttributeValueType;
import at.procon.dip.domain.document.DocumentFamily;
import at.procon.dip.domain.document.DocumentStatus;
import at.procon.dip.domain.document.DocumentType;
import at.procon.dip.domain.document.RepresentationType;
import at.procon.dip.domain.document.SourceType;
import at.procon.dip.domain.document.entity.Document;
import at.procon.dip.domain.document.entity.DocumentAttribute;
import at.procon.dip.domain.document.entity.DocumentAttributeName;
import at.procon.dip.domain.document.entity.DocumentSource;
import at.procon.dip.domain.document.entity.DocumentTextRepresentation;
import at.procon.dip.domain.document.repository.DocumentAttributeRepository;
import at.procon.dip.domain.document.repository.DocumentRepository;
import at.procon.dip.domain.document.repository.DocumentSourceRepository;
import at.procon.dip.domain.document.repository.DocumentTextRepresentationRepository;
import java.time.OffsetDateTime;
import java.util.List;
import java.util.Optional;
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 GenericDocumentReadServiceTest {

    @Mock private DocumentRepository documentRepository;
    @Mock private DocumentAttributeRepository documentAttributeRepository;
    @Mock private DocumentSourceRepository documentSourceRepository;
    @Mock private DocumentTextRepresentationRepository documentTextRepresentationRepository;

    private GenericDocumentReadService service;

    @BeforeEach
    void setUp() {
        service = new GenericDocumentReadService(documentRepository, documentAttributeRepository, documentSourceRepository, documentTextRepresentationRepository);
    }

    @Test
    void shouldReturnDocumentDetailWithAttributesSourcesAndRepresentations() {
        UUID documentId = UUID.randomUUID();
        Document document = Document.builder()
                .id(documentId)
                .visibility(DocumentVisibility.PUBLIC)
                .documentType(DocumentType.TEXT)
                .documentFamily(DocumentFamily.GENERIC)
                .status(DocumentStatus.REPRESENTED)
                .title("Doc")
                .languageCode("de")
                .mimeType("text/plain")
                .businessKey("API:ext-1")
                .dedupHash("abc")
                .build();
        when(documentRepository.findById(documentId)).thenReturn(Optional.of(document));
        when(documentAttributeRepository.findByDocument_IdOrderByAttributeName_AttributeContextAscAttributeName_AttributeNameAsc(documentId))
                .thenReturn(List.of(DocumentAttribute.builder()
                        .id(UUID.randomUUID())
                        .document(document)
                        .attributeName(DocumentAttributeName.builder()
                                .id(UUID.randomUUID())
                                .attributeName("status")
                                .normalizedName("status")
                                .attributeContext("TED")
                                .attributeValueType(DocumentAttributeValueType.STRING)
                                .build())
                        .stringValue("closed")
                        .createdAt(OffsetDateTime.now())
                        .attributeValueHash("x")
                        .build()));
        when(documentSourceRepository.findByDocument_Id(documentId))
                .thenReturn(List.of(DocumentSource.builder()
                        .id(UUID.randomUUID())
                        .document(document)
                        .sourceType(SourceType.API)
                        .externalSourceId("ext-1")
                        .sourceFilename("sample.txt")
                        .receivedAt(OffsetDateTime.now())
                        .build()));
        when(documentTextRepresentationRepository.findByDocument_Id(documentId))
                .thenReturn(List.of(DocumentTextRepresentation.builder()
                        .id(UUID.randomUUID())
                        .document(document)
                        .representationType(RepresentationType.SEMANTIC_TEXT)
                        .primaryRepresentation(true)
                        .textBody("hello world")
                        .build()));

        var response = service.findById(documentId);

        assertThat(response).isPresent();
        assertThat(response.get().id()).isEqualTo(documentId);
        assertThat(response.get().attributes()).hasSize(1);
        assertThat(response.get().attributes().getFirst().context()).isEqualTo("TED");
        assertThat(response.get().sources()).hasSize(1);
        assertThat(response.get().sources().getFirst().externalSourceId()).isEqualTo("ext-1");
        assertThat(response.get().representations()).hasSize(1);
        assertThat(response.get().representations().getFirst().textPreview()).isEqualTo("hello world");
    }
}
