package com.iqser.red.service.persistence.service.v1.api.shared.mongo.service;

import java.util.ArrayList;
import java.util.List;

import org.bson.Document;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.entitylog.EntityLog;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.document.EntityLogDocument;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.document.EntityLogEntryDocument;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.mapper.EntityLogDocumentMapper;
import com.mongodb.DBRef;

@Service
public class EntityLogDocumentUpdateService {

    public static final String ENTITY_LOG_ENTRY_DOCUMENTS = "entityLogEntryDocuments";
    private final MongoTemplate mongoTemplate;
    private final EntityLogDocumentMapper mapper = EntityLogDocumentMapper.INSTANCE;


    public EntityLogDocumentUpdateService(MongoTemplate mongoTemplate) {this.mongoTemplate = mongoTemplate;}


    public void updateEntityLogDocumentWithoutEntries(String dossierId, String fileId, EntityLog entityLog) {

        Document doc = new Document();
        mongoTemplate.getConverter().write(mapper.toLogDocument(dossierId, fileId, entityLog), doc);
        doc.remove(ENTITY_LOG_ENTRY_DOCUMENTS);

        Update update = new Update();
        doc.forEach(update::set);
        mongoTemplate.updateFirst(getIdQuery(mapper.getLogId(dossierId, fileId)), update, EntityLogDocument.class);
    }


    public void addEntityLogEntryReferences(String entityLogId, List<EntityLogEntryDocument> newEntries) {

        List<DBRef> dbRefs = convertEntriesToDbRefs(newEntries);
        Update update = new Update().push(ENTITY_LOG_ENTRY_DOCUMENTS).each(dbRefs.toArray());
        mongoTemplate.updateFirst(getIdQuery(entityLogId), update, EntityLogDocument.class);
    }

    public void removeEntityLogEntryReferences(String entityLogId, List<EntityLogEntryDocument> entriesToRemove) {

        List<DBRef> dbRefs = convertEntriesToDbRefs(entriesToRemove);
        Update update = new Update().pullAll(ENTITY_LOG_ENTRY_DOCUMENTS, dbRefs.toArray());
        mongoTemplate.updateFirst(getIdQuery(entityLogId), update, EntityLogDocument.class);
    }


    private static List<DBRef> convertEntriesToDbRefs(List<EntityLogEntryDocument> entriesToRemove) {

        List<DBRef> dbRefs = new ArrayList<>();
        for (EntityLogEntryDocument entry : entriesToRemove) {
            DBRef dbRef = new DBRef("entity-log-entries", entry.getId());
            dbRefs.add(dbRef);
        }
        return dbRefs;
    }


    private Query getIdQuery(String mapper) {

        return Query.query(Criteria.where("_id").is(mapper));
    }

}
