package com.zhongshu.card.server.core.dao.dictionary.impl;

import com.github.microservice.components.data.mongo.mongo.helper.DBHelper;
import com.mongodb.client.MongoCollection;
import com.zhongshu.card.client.model.dictionary.DictionaryItemModel;
import com.zhongshu.card.server.core.dao.dictionary.extend.DictionaryItemDaoExtend;
import com.zhongshu.card.server.core.domain.dictionary.DictionaryItem;
import com.zhongshu.card.server.core.model.dictionary.DItemChildrenResult;
import org.apache.commons.lang3.StringUtils;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import javax.imageio.metadata.IIOMetadataFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;

public class DictionaryItemDaoImpl implements DictionaryItemDaoExtend {

    @Autowired
    DBHelper dbHelper;

    @Autowired
    MongoTemplate mongoTemplate;

    @Override
    public Page<DictionaryItem> page(Pageable pageable, String dictionaryId, String name, String parentId) {
        Criteria criteria = new Criteria();

        if (StringUtils.isNotBlank(name)) {
            Pattern pattern = Pattern.compile("^.*" + name + ".*$");
            criteria.orOperator(Criteria.where("name").regex(pattern), Criteria.where("key").regex(pattern));
        }

        if (StringUtils.isNotBlank(parentId)) {
            criteria.and("parentId").is(parentId);
        }else {
            criteria.and("parentId").isNull();
        }

        criteria.and("dictionary._id").is(dictionaryId);
        Query query = Query.query(criteria);
        query.with(Sort.by(Sort.Order.asc("sort"), Sort.Order.desc("createTime")));

        return dbHelper.pages(query, pageable, DictionaryItem.class);
    }

    @Override
    public List<DictionaryItemModel> deepAggregate(String dictionaryId, List<String> keys) {

        List<Document> pipeline =  new ArrayList<>() {{
                add(new Document()
                        .append("$match", new Document()
                                .append("key", new Document()
                                        .append("$in", keys
                                        )
                                )
                                .append("dictionary", new Document()
                                        .append("$ref", "dictionary")
                                        .append("$id", new ObjectId(dictionaryId))
                                )
                        ));
        }};

        pipeline.add( new Document()
                .append("$graphLookup", new Document()
                        .append("from", "dictionaryItem")
                        .append("startWith", "$idString")
                        .append("connectFromField", "idString")
                        .append("connectToField", "parentId")
                        .append("as", "children")
                        .append("depthField", "level")
                ));
        final MongoCollection<Document> collection = this.mongoTemplate.getCollection(this.mongoTemplate.getCollectionName(DictionaryItem.class));

        List<DictionaryItemModel> ret = new ArrayList<>();


        collection.aggregate(pipeline).allowDiskUse(false).forEach((document)->{
            Optional.ofNullable(document).ifPresent((it) -> {
                ret.add(this.mongoTemplate.getConverter().read(DictionaryItemModel.class, it));
            });
        });
        return ret;
    }
}
