package com.iqser.red.service.peristence.v1.server.integration.tests;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.List;
import java.util.stream.Collectors;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

import com.iqser.red.service.peristence.v1.server.integration.service.DossierTemplateTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.FileTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.TypeProvider;
import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest;
import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.ManualRedactionEntryEntity;
import com.iqser.red.service.persistence.management.v1.processor.service.manualredactions.PendingEntryFactory;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.annotationentity.ManualRedactionRepository;
import com.iqser.red.service.persistence.management.v1.processor.service.queue.SearchTermOccurrencesResponseReceiver;
import com.iqser.red.service.persistence.service.v1.api.shared.model.BulkLocalResponse;
import com.iqser.red.service.persistence.service.v1.api.shared.model.FoundTerm;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLogEntry;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.Position;
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Rectangle;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.ProcessingStatus;
import com.iqser.red.service.persistence.service.v1.api.shared.model.manual.AddRedactionBulkLocalRequestModel;

import lombok.AccessLevel;
import lombok.experimental.FieldDefaults;

@FieldDefaults(level = AccessLevel.PRIVATE)
public class SearchTermOccurrencesTest extends AbstractPersistenceServerServiceTest {

    @Autowired
    FileTesterAndProvider fileTesterAndProvider;
    @Autowired
    DossierTesterAndProvider dossierTesterAndProvider;
    @Autowired
    DossierTemplateTesterAndProvider dossierTemplateTesterAndProvider;
    @Autowired
    TypeProvider typeProvider;
    @Autowired
    SearchTermOccurrencesResponseReceiver searchTermOccurrencesResponseReceiver;
    @Autowired
    FileStatusPersistenceService fileStatusPersistenceService;
    @Autowired
    ManualRedactionRepository manualRedactionRepository;
    @Autowired
    PendingEntryFactory pendingEntryFactory;


    @Test
    public void testBulkLocal() {

        var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
        var dossier = dossierTesterAndProvider.provideTestDossier(dossierTemplate);
        var file = fileTesterAndProvider.testAndProvideFile(dossier);
        var type = typeProvider.testAndProvideType(dossierTemplate, dossier, "test", false, 70);

        fileStatusPersistenceService.updateProcessingStatus(file.getFileId(), ProcessingStatus.BULK_LOCAL_REDACTIONS_PROCESSING);

        searchTermOccurrencesResponseReceiver.receive(BulkLocalResponse.builder()
                                                              .fileId(file.getId())
                                                              .dossierId(dossier.getId())
                                                              .type(type.getType())
                                                              .legalBasis("legalBasis")
                                                              .reason("reason")
                                                              .section("section")
                                                              .foundTerms(List.of(new FoundTerm(List.of(new Position(new float[]{1f, 2f, 3f, 4f}, 1)), "searchTerm")))
                                                              .comment(null)
                                                              .userId("MyUser")
                                                              .build());

        List<ManualRedactionEntryEntity> newEntries = manualRedactionRepository.findByFileIdAndOptions(file.getId(), false, false, false);
        assertEquals(newEntries.size(), 1);
        assertEquals(newEntries.get(0).getValue(), "searchTerm");
        assertEquals(newEntries.get(0).getLegalBasis(), "legalBasis");
        assertEquals(newEntries.get(0).getReason(), "reason");
        assertEquals(newEntries.get(0).getSection(), "section");
        assertEquals(fileStatusPersistenceService.getStatus(file.getId()).getProcessingStatus(), ProcessingStatus.PROCESSED);

    }


    @Test
    public void testPendingEntryCreation() {

        AddRedactionBulkLocalRequestModel addRedactionBulkLocalRequestModel = AddRedactionBulkLocalRequestModel.builder()
                .value("Max")
                .type("123")
                .legalBasis("legalbasis")
                .reason("reason")
                .section("section")
                .positions(List.of(new Rectangle(333.92593f, 446.8f, 19.152008f, 11.81175f, 1)))
                .build();
        EntityLogEntry entityLogEntry = pendingEntryFactory.buildAddRedactionBulkLocalEntry(addRedactionBulkLocalRequestModel);
        List<Position> positions = convertPositions(addRedactionBulkLocalRequestModel.getPositions());
        assertEquals(entityLogEntry.getPositions()
                             .get(0), positions.get(0));
        assertEquals(entityLogEntry.getValue(), addRedactionBulkLocalRequestModel.getValue());
        assertEquals(entityLogEntry.getLegalBasis(), addRedactionBulkLocalRequestModel.getLegalBasis());
        assertEquals(entityLogEntry.getReason(), addRedactionBulkLocalRequestModel.getReason());
        assertEquals(entityLogEntry.getSection(), addRedactionBulkLocalRequestModel.getSection());

    }


    private List<Position> convertPositions(List<Rectangle> rectangles) {

        return rectangles.stream()
                .map(rectangle -> new Position(rectangle.getTopLeftX(), rectangle.getTopLeftY(), rectangle.getWidth(), rectangle.getHeight(), rectangle.getPage()))
                .collect(Collectors.toList());
    }

}
