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

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

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

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

import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.CommentEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.ManualRedactionEntryEntity;
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.CommentPersistenceService;
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.ManualImageRecategorizationMapper;
import com.iqser.red.service.persistence.management.v1.processor.utils.ManualRedactionMapper;
import com.iqser.red.service.persistence.management.v1.processor.utils.ManualResizeRedactionMapper;
import com.iqser.red.service.persistence.service.v1.api.shared.model.annotations.Comment;
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 CommentPersistenceService commentPersistenceService;
    private final RecategorizationPersistenceService recategorizationPersistenceService;
    private final LegalBasisChangePersistenceService legalBasisChangePersistenceService;
    private final ResizeRedactionPersistenceService resizeRedactionPersistenceService;


    @Transactional
    public ManualRedactions getManualRedactions(String fileId) {

        Set<ManualRedactionEntry> entriesToAdd = convertEntriesToAdd(addRedactionPersistenceService.findAddRedactions(fileId, false));

        Set<IdRemoval> removals = convert(removeRedactionPersistenceService.findRemoveRedactions(fileId, false), IdRemoval.class);

        Set<ManualForceRedaction> forceRedactions = convert(forceRedactionPersistenceService.findForceRedactions(fileId, false), ManualForceRedaction.class);

        Set<ManualRecategorization> recategorizations = new HashSet<>(convert(recategorizationPersistenceService.findRecategorizations(fileId, false),
                ManualRecategorization.class,
                new ManualImageRecategorizationMapper()));

        Set<ManualLegalBasisChange> legalBasisChanges = convert(legalBasisChangePersistenceService.findLegalBasisChanges(fileId, false), ManualLegalBasisChange.class);

        Set<ManualResizeRedaction> resizeRedactions = new HashSet<>(convert(resizeRedactionPersistenceService.findResizeRedactions(fileId, false),
                ManualResizeRedaction.class,
                new ManualResizeRedactionMapper()));

        Map<String, List<CommentEntity>> commentEntities = commentPersistenceService.findCommentsByFileID(fileId, false);

        Map<String, List<Comment>> comments = new HashMap<>();
        commentEntities.forEach((s, c) -> comments.put(s, convert(c, Comment.class)));

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


    @Transactional
    public ManualRedactionEntry getAddRedaction(String fileId, String annotationId) {

        return convert(addRedactionPersistenceService.findAddRedaction(fileId, annotationId), ManualRedactionEntry.class, new ManualRedactionMapper());
    }


    private Set<ManualRedactionEntry> convertEntriesToAdd(List<ManualRedactionEntryEntity> source) {

        return source.stream().map(entry -> convert(entry, ManualRedactionEntry.class, new ManualRedactionMapper())).collect(Collectors.toSet());
    }


    @Transactional(noRollbackFor = {EmptyResultDataAccessException.class})
    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);
        commentPersistenceService.hardDelete(fileId, annotationId);
    }

}
