package com.iqser.red.service.persistence.management.v1.processor.service.manualredactions;

import static com.knecon.fforesight.databasetenantcommons.providers.utils.MagicConverter.convert;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.iqser.red.service.persistence.management.v1.processor.model.ManualChangesQueryOptions;
import com.iqser.red.service.persistence.management.v1.processor.service.CommentService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.AddRedactionPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.ForceRedactionPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.LegalBasisChangePersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.RecategorizationPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.RemoveRedactionPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.ResizeRedactionPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.utils.ManualRecategorizationMapper;
import com.iqser.red.service.persistence.management.v1.processor.utils.ManualRedactionEntryMapper;
import com.iqser.red.service.persistence.management.v1.processor.utils.ManualResizeRedactionMapper;
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.ManualRedactions;
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.IdRemoval;
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualForceRedaction;
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualLegalBasisChange;
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualRecategorization;
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualRedactionEntry;
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.entitymapped.ManualResizeRedaction;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@RequiredArgsConstructor
public class ManualRedactionProviderService {

    private final AddRedactionPersistenceService addRedactionPersistenceService;
    private final RemoveRedactionPersistenceService removeRedactionPersistenceService;
    private final ForceRedactionPersistenceService forceRedactionPersistenceService;
    private final CommentService commentService;
    private final RecategorizationPersistenceService recategorizationPersistenceService;
    private final LegalBasisChangePersistenceService legalBasisChangePersistenceService;
    private final ResizeRedactionPersistenceService resizeRedactionPersistenceService;


    public void convertUnprocessedAddToDictionariesToLocalChanges(String fileId) {

        var unprocessedManualAdds = addRedactionPersistenceService.findEntriesByFileIdAndOptions(fileId, ManualChangesQueryOptions.unprocessedOnly());
        for (var unprocessedManualAdd : unprocessedManualAdds) {
            if (unprocessedManualAdd.isAddToDictionary() || unprocessedManualAdd.isAddToAllDossiers()) {
                unprocessedManualAdd.setAddToDictionary(false);
                unprocessedManualAdd.setAddToAllDossiers(false);
                unprocessedManualAdd.setLegalBasis("");
                addRedactionPersistenceService.update(unprocessedManualAdd);
            }
        }
    }


    @Transactional
    public ManualRedactions getManualRedactions(String fileId, ManualChangesQueryOptions options) {

        Set<ManualRedactionEntry> entriesToAdd;
        Set<IdRemoval> removals;
        Set<ManualForceRedaction> forceRedactions;
        Set<ManualRecategorization> recategorizations;
        Set<ManualLegalBasisChange> legalBasisChanges;
        Set<ManualResizeRedaction> resizeRedactions;

        if (!options.getExcludedClasses().contains(ManualRedactionEntry.class)) {
            entriesToAdd = new HashSet<>(convert(addRedactionPersistenceService.findEntriesByFileIdAndOptions(fileId, options),
                                                 ManualRedactionEntry.class,
                                                 new ManualRedactionEntryMapper()));
        } else {
            entriesToAdd = Collections.emptySet();
        }

        if (!options.getExcludedClasses().contains(ManualRecategorization.class)) {
            recategorizations = new HashSet<>(convert(recategorizationPersistenceService.findEntriesByFileIdAndOptions(fileId, options),
                                                      ManualRecategorization.class,
                                                      new ManualRecategorizationMapper()));
        } else {
            recategorizations = Collections.emptySet();
        }

        if (!options.getExcludedClasses().contains(ManualResizeRedaction.class)) {
            resizeRedactions = new HashSet<>(convert(resizeRedactionPersistenceService.findEntriesByFileIdAndOptions(fileId, options),
                                                     ManualResizeRedaction.class,
                                                     new ManualResizeRedactionMapper()));
        } else {
            resizeRedactions = Collections.emptySet();
        }

        if (!options.getExcludedClasses().contains(IdRemoval.class)) {
            removals = new HashSet<>(convert(removeRedactionPersistenceService.findEntriesByFileIdAndOptions(fileId, options), IdRemoval.class));
        } else {
            removals = Collections.emptySet();
        }

        if (!options.getExcludedClasses().contains(ManualForceRedaction.class)) {
            forceRedactions = new HashSet<>(convert(forceRedactionPersistenceService.findEntriesByFileIdAndOptions(fileId, options), ManualForceRedaction.class));
        } else {
            forceRedactions = Collections.emptySet();
        }

        if (!options.getExcludedClasses().contains(ManualLegalBasisChange.class)) {
            legalBasisChanges = new HashSet<>(convert(legalBasisChangePersistenceService.findEntriesByFileIdAndOptions(fileId, options), ManualLegalBasisChange.class));
        } else {
            legalBasisChanges = Collections.emptySet();
        }

        return new ManualRedactions(removals, entriesToAdd, forceRedactions, recategorizations, legalBasisChanges, resizeRedactions);

    }


    @Transactional(noRollbackFor = {EmptyResultDataAccessException.class}, propagation = Propagation.REQUIRES_NEW)
    public void hardDeleteManualRedactions(String fileId, String annotationId) {

        addRedactionPersistenceService.hardDelete(fileId, annotationId);
        removeRedactionPersistenceService.hardDelete(fileId, annotationId);
        forceRedactionPersistenceService.hardDelete(fileId, annotationId);
        recategorizationPersistenceService.hardDelete(fileId, annotationId);
        legalBasisChangePersistenceService.hardDelete(fileId, annotationId);
        resizeRedactionPersistenceService.hardDelete(fileId, annotationId);
        commentService.hardDelete(fileId, annotationId);
    }

}
