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

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;

import org.springframework.stereotype.Service;

import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.AnnotationEntityId;
import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.ManualRedactionEntryEntity;
import com.iqser.red.service.persistence.management.v1.processor.model.ManualChangesQueryOptions;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.annotations.AddRedactionPersistenceService;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.type.DictionaryEntryType;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class SaasMigrationManualChangesUpdateService {

    private final AddRedactionPersistenceService addRedactionPersistenceService;

    private final HashFunction hashFunction = Hashing.murmur3_128();


    public void convertUnprocessedAddToDictionariesToLocalChanges(String fileId) {

        var unprocessedManualAdds = addRedactionPersistenceService.findEntriesByFileIdAndOptions(fileId, ManualChangesQueryOptions.unprocessedOnly());
        for (var unprocessedManualAdd : unprocessedManualAdds) {

            if (!unprocessedManualAdd.getDictionaryEntryType().equals(DictionaryEntryType.ENTRY)) {
                continue;
            }

            if (unprocessedManualAdd.isAddToDictionary() || unprocessedManualAdd.isAddToAllDossiers()) {
                // copy pending dict change to a new one with a different id. Can't reuse the same one, as it's the primary key of the table.
                // It has no functionality, its only there, such that the UI can show a pending change.
                ManualRedactionEntryEntity pendingDictAdd = new ManualRedactionEntryEntity(buildSecondaryId(unprocessedManualAdd.getId(), fileId),
                                                                                           unprocessedManualAdd.getUser(),
                                                                                           unprocessedManualAdd.getTypeId(),
                                                                                           unprocessedManualAdd.getValue(),
                                                                                           unprocessedManualAdd.getReason(),
                                                                                           unprocessedManualAdd.getLegalBasis(),
                                                                                           unprocessedManualAdd.getSection(),
                                                                                           unprocessedManualAdd.isRectangle(),
                                                                                           unprocessedManualAdd.isAddToDictionary(),
                                                                                           unprocessedManualAdd.isAddToAllDossiers(),
                                                                                           unprocessedManualAdd.isAddToDossierDictionary(),
                                                                                           DictionaryEntryType.ENTRY,
                                                                                           unprocessedManualAdd.getRequestDate(),
                                                                                           null,
                                                                                           null,
                                                                                           new ArrayList<>(unprocessedManualAdd.getPositions()),
                                                                                           unprocessedManualAdd.getFileStatus(),
                                                                                           unprocessedManualAdd.getTextBefore(),
                                                                                           unprocessedManualAdd.getTextAfter(),
                                                                                           unprocessedManualAdd.getSourceId(),
                                                                                           new HashSet<>(unprocessedManualAdd.getTypeIdsOfModifiedDictionaries()));

                addRedactionPersistenceService.update(pendingDictAdd);

                // change existing dict add to unprocessed manual add. ID must match with prior entry, such that other unprocessed manual changes may be applied to it.
                unprocessedManualAdd.setAddToDictionary(false);
                unprocessedManualAdd.setAddToAllDossiers(false);
                unprocessedManualAdd.setLegalBasis("");
                unprocessedManualAdd.setTypeIdsOfModifiedDictionaries(Collections.emptySet());
                unprocessedManualAdd.setDictionaryEntryType(null);

                addRedactionPersistenceService.update(unprocessedManualAdd);
            }
        }
    }


    private AnnotationEntityId buildSecondaryId(AnnotationEntityId annotationEntityId, String fileId) {

        return new AnnotationEntityId(hashFunction.hashString(annotationEntityId.getAnnotationId(), StandardCharsets.UTF_8).toString(), fileId);
    }

}
