package com.iqser.red.service.persistence.management.v1.processor.migration.migrations;

import java.time.OffsetDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import org.springframework.stereotype.Service;

import com.iqser.red.service.persistence.management.v1.processor.migration.Migration;
import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.AddRedactionPersistenceService;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.ManualChange;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.ManualRedactionType;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.repository.EntityLogEntryDocumentRepository;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.repository.projections.EntryWithManualChangesProjection;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class V23ManualChangesReorderingMigration extends Migration {

    private static final String NAME = "Migration for reordering mixed up manual changes";
    private static final long VERSION = 23;
    private final EntityLogEntryDocumentRepository entityLogEntryDocumentRepository;
    private final AddRedactionPersistenceService addRedactionPersistenceService;
    private final FileStatusService fileStatusService;


    public V23ManualChangesReorderingMigration(EntityLogEntryDocumentRepository entityLogEntryDocumentRepository,
                                               AddRedactionPersistenceService addRedactionPersistenceService,
                                               FileStatusService fileStatusService) {

        super(NAME, VERSION);
        this.entityLogEntryDocumentRepository = entityLogEntryDocumentRepository;
        this.addRedactionPersistenceService = addRedactionPersistenceService;
        this.fileStatusService = fileStatusService;
    }


    @Override
    protected void migrate() {

        log.info("Searching for entityLogEntries of type ENTITY with state APPLIED and no legalbasis");
        List<EntryWithManualChangesProjection> entriesWithManualChanges = entityLogEntryDocumentRepository.findAppliedEntitiesWhereLegalBasisEmpty();
        log.info("Found {} applied entries with no legal basis", entriesWithManualChanges.size());
        int numberOfChanged = 0;
        Set<FileAndDossier> affectedFiles = new HashSet<>();
        for (EntryWithManualChangesProjection entry : entriesWithManualChanges) {
            if (entry.getManualChanges().isEmpty()) {
                continue;
            }
            Optional<ManualChange> optionalAdd = entry.getManualChanges()
                    .stream()
                    .filter(mc -> mc.getManualRedactionType().equals(ManualRedactionType.ADD))
                    .findFirst();
            if (optionalAdd.isEmpty()) {
                continue;
            }
            ManualChange add = optionalAdd.get();
            ManualChange first = entry.getManualChanges()
                    .get(0);
            if (add.equals(first)) {
                continue;
            }
            OffsetDateTime firstTimestamp = first.getRequestedDate().minusSeconds(1);
            String dossierId = entry.getEntityLogId().split("/")[0];
            String fileId = entry.getEntityLogId().split("/")[1];
            int i = addRedactionPersistenceService.updateRequestDate(fileId, entry.getEntryId(), firstTimestamp);
            if (i != 0) {
                affectedFiles.add(new FileAndDossier(fileId, dossierId));
                numberOfChanged += i;
            }
        }
        log.info("Updated request date of {} manual add redactions in {} files.", numberOfChanged, affectedFiles.size());
        log.info("Reanalyzing affected files");
        for (FileAndDossier affectedFile : affectedFiles) {
            fileStatusService.setStatusReprocess(affectedFile.dossierId(), affectedFile.fileId(), false);
        }

    }


    private record FileAndDossier(String fileId, String dossierId) {

    }

}
