package cn.reghao.tnb.search.app.comment.db.mongo;

import cn.reghao.jutil.jdk.web.db.BaseCrud;
import cn.reghao.jutil.jdk.web.db.BaseQuery;
import cn.reghao.jutil.jdk.web.db.PageList;
import cn.reghao.tnb.search.app.comment.model.po.RichText;
import cn.reghao.tnb.search.app.comment.model.vo.NewsPost;
import com.mongodb.MongoBulkWriteException;
import com.mongodb.client.model.InsertManyOptions;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.InsertManyResult;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author reghao
 * @date 2023-02-01 14:19:02
 */
@Slf4j
@Repository
public class RichTextMongo implements BaseCrud<RichText>, BaseQuery<RichText> {
    private final String colName = "RichText";
    private final MongoTemplate mongoTemplate;
    private final MongoConverter mongoConverter;
    private final int pageSize = 20;

    public RichTextMongo(MongoTemplate mongoTemplate, MongoConverter mongoConverter) {
        this.mongoTemplate = mongoTemplate;
        this.mongoConverter = mongoConverter;
    }

    @Override
    public RichText save(RichText richText) {
        Document doc = new Document();
        mongoConverter.write(richText, doc);
        mongoTemplate.getCollection(colName).insertOne(doc);
        return null;
    }

    @Override
    public void saveAll(List<RichText> list) {
        List<Document> documents = list.stream()
                .map(t -> {
                    Document doc = new Document();
                    mongoConverter.write(t, doc);
                    return doc;
                })
                .collect(Collectors.toList());

        InsertManyOptions options = new InsertManyOptions();
        // 忽略 insert 失败的文档
        options.ordered(false);
        try {
            InsertManyResult result = mongoTemplate.getCollection(colName).insertMany(documents, options);
        }  catch (MongoBulkWriteException ignore) {
        }
    }

    @Override
    public void update(RichText richText) {
        richText.setUpdateTime(LocalDateTime.now());

        Document document = new Document();
        mongoConverter.write(richText, document);
        Document filter = new Document();
        filter.put("contentId", richText.getContentId());
        mongoTemplate.getCollection(colName).replaceOne(filter, document);
    }

    @Override
    public void delete(RichText richText) {
        Query query = new Query();
        query.addCriteria(Criteria.where("contentId").is(richText.getContentId()));
        DeleteResult deleteResult = mongoTemplate.remove(query, colName);
        if (deleteResult.getDeletedCount() != 1) {
        }
    }

    public long countByUserId(long userId) {
        Document filter = new Document();
        filter.put("userId", userId);
        return mongoTemplate.getCollection(colName).countDocuments(filter);
    }

    public PageList<NewsPost> findNewsPostByPage(long page) {
        Query query = new Query();
        query.addCriteria(Criteria.where("content").ne(null));
        query.skip((page - 1) * pageSize).limit(pageSize);
        query.with(Sort.by(new Sort.Order(Sort.Direction.DESC, "publishAt")));
        List<RichText> list = mongoTemplate.find(query, RichText.class, colName);
        List<NewsPost> list1 = list.stream()
                .map(NewsPost::new)
                .collect(Collectors.toList());
        int total = list.size();
        return PageList.pageList((int) page, pageSize, total, list1);
    }

    public List<RichText> findByContentIsNull() {
        Query query = new Query();
        query.addCriteria(Criteria.where("content").is(null));
        query.skip(0).limit(1000);
        query.with(Sort.by(new Sort.Order(Sort.Direction.DESC, "publishAt")));
        return mongoTemplate.find(query, RichText.class, colName);
    }

    public RichText findByOriginalUrl(String originalUrl) {
        Query query = new Query();
        query.addCriteria(Criteria.where("originalUrl").is(originalUrl));
        List<RichText> list = mongoTemplate.find(query, RichText.class, colName);
        return list.isEmpty() ? null : list.get(0);
    }

    public RichText findByContentId(long contentId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("contentId").is(contentId));
        List<RichText> list = mongoTemplate.find(query, RichText.class, colName);
        return list.isEmpty() ? null : list.get(0);
    }
}
