package org.lym.pom.service.impl;

import com.mongodb.client.result.UpdateResult;
import org.lym.pom.notify.event.PostAddEvent;
import org.lym.pom.notify.event.PostRemoveEvent;
import org.lym.pom.notify.publisher.EventPublisher;
import org.lym.pom.repository.PostRepository;
import org.lym.pom.repository.mongo.Post;
import org.lym.pom.repository.mongo.enums.PostStatusEnum;
import org.lym.pom.service.PostService;
import org.shoulder.core.exception.CommonErrorCodeEnum;
import org.shoulder.core.util.AssertUtils;
import org.springframework.beans.factory.annotation.Autowired;
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 java.util.List;
import java.util.Set;

/**
 * 订阅推送服务
 *
 * @author lym
 */
@Service
public class PostServiceImpl implements PostService {

    @Autowired
    private EventPublisher eventPublisher;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private PostRepository postRepository;

    @Override public Post addPost(Post post) {

        AssertUtils.notEmpty(post.getTitle(), CommonErrorCodeEnum.ILLEGAL_PARAM);
        AssertUtils.notEmpty(post.getContent(), CommonErrorCodeEnum.ILLEGAL_PARAM);
        AssertUtils.notEmpty(post.getType(), CommonErrorCodeEnum.ILLEGAL_PARAM);
        AssertUtils.notEmpty(post.getVisibility(), CommonErrorCodeEnum.ILLEGAL_PARAM);
        AssertUtils.notEmpty(post.getCreator(), CommonErrorCodeEnum.ILLEGAL_PARAM);
        AssertUtils.notEmpty(post.getDevice(), CommonErrorCodeEnum.ILLEGAL_PARAM);

        post.setStatus(PostStatusEnum.NORMAL.getStorageName());
        post.setCreateTime(System.currentTimeMillis());
        post.setUpdateTime(post.getCreateTime());
        post = postRepository.save(post);

        eventPublisher.publish(new PostAddEvent(post));
        return post;
    }

    @Override
    public void removePost(String postId) {
        Post postInDb = postRepository.findById(postId).orElse(null);
        if(postInDb == null || postInDb.getStatus().equals(PostStatusEnum.DELETED.getStorageName())) {
            return;
        }

        // 更新状态
        Query queryById = new Query(Criteria.where("id").is(postId));
        Update update = Update.update("status", PostStatusEnum.DELETED.getStorageName())
                .set("updateTime", System.currentTimeMillis());
        UpdateResult updateResult = mongoTemplate.updateFirst(queryById, update, Post.class);
        AssertUtils.equals(updateResult.getMatchedCount(), updateResult.getModifiedCount(), CommonErrorCodeEnum.DATA_STORAGE_FAIL);
        AssertUtils.isTrue( updateResult.getModifiedCount() > 0, CommonErrorCodeEnum.DATA_STORAGE_FAIL);

        eventPublisher.publish(new PostRemoveEvent(postInDb));
    }

    @Override
    public Post queryPostDetail(String id) {
        return mongoTemplate.findOne(new Query(Criteria.where("id").is(id)
                .and("status").ne(PostStatusEnum.DELETED.getStorageName())), Post.class);
    }

    @Override public List<Post> queryListByIds(Set<String> ids) {
        return mongoTemplate.find(new Query(Criteria.where("id").in(ids).and("status").ne(PostStatusEnum.DELETED.getStorageName())), Post.class);
    }

}
