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

import java.time.OffsetDateTime;
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.componentlog.ComponentLog;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.componentlog.ComponentLogEntryValue;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.document.ComponentLogDocument;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.document.ComponentLogEntryDocument;
import com.iqser.red.service.persistence.service.v1.api.shared.mongo.mapper.ComponentLogDocumentMapper;
import com.mongodb.DBRef;

@Service
public class ComponentLogDocumentUpdateService {

    public static final String COMPONENT_LOG_ENTRY_DOCUMENTS = "componentLogEntryDocuments";
    private final MongoTemplate mongoTemplate;
    private final ComponentLogDocumentMapper mapper = ComponentLogDocumentMapper.INSTANCE;


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


    public void updateComponentLogDocumentWithoutEntries(String dossierId, String fileId, ComponentLog componentLog) {

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

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


    public void addComponentLogEntryReferences(String componentLogId, List<ComponentLogEntryDocument> newEntries) {

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


    public void removeComponentLogEntryReferences(String componentLogId, List<ComponentLogEntryDocument> entriesToRemove) {

        List<DBRef> dbRefs = convertEntriesToDbRefs(entriesToRemove);
        Update update = new Update().pullAll(COMPONENT_LOG_ENTRY_DOCUMENTS, dbRefs.toArray());
        mongoTemplate.updateFirst(getIdQuery(componentLogId), update, ComponentLogDocument.class);
    }


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

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


    private Query getIdQuery(String id) {

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

    public void updateComponentLogEntryDocumentValues(String id, List<ComponentLogEntryValue> overriddenValues, boolean overridden) {

        Update update = new Update()
                .set("values", overriddenValues)
                .set("overridden", overridden);

        mongoTemplate.updateFirst(getIdQuery(id), update, ComponentLogEntryDocument.class);
    }






//    public void setSoftDeletedTime(String componentLogId, OffsetDateTime softDeletedTime) {
//
//        Query query = new Query(Criteria.where("componentLogId").is(componentLogId).and("softDeletedTime").is(null));
//
//        Update update = new Update().set("softDeletedTime", softDeletedTime);
//        mongoTemplate.updateMulti(query, update, ComponentLogEntryDocument.class);
//
//    }
//
//
//    public void unsetSoftDeletedTimeWhereGreaterThanEquals(String componentLogId, OffsetDateTime softDeletedTime) {
//
//        Query query = new Query(Criteria.where("componentLogId").is(componentLogId).and("softDeletedTime").gte(softDeletedTime));
//
//        Update update = new Update().unset("softDeletedTime");
//        mongoTemplate.updateMulti(query, update, ComponentLogEntryDocument.class);
//
//    }

}
