package com.apobates.forum.core.impl.dao;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Optional;
import java.util.stream.Stream;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.apobates.forum.core.api.dao.TopicStatsDao;
import com.apobates.forum.core.entity.TopicStats;

@Repository
public class TopicStatsDaoImpl implements TopicStatsDao{
	@PersistenceContext
	private EntityManager entityManager;
	private final static Logger logger = LoggerFactory.getLogger(TopicStatsDaoImpl.class);
	
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public void save(TopicStats entity) {
		entityManager.persist(entity);
	}

	@Override
	public Optional<TopicStats> findOne(Long primaryKey) {
		return Optional.empty();
	}

	@Override
	public Optional<Boolean> edit(TopicStats updateEntity) {
		return Optional.empty();
	}

	@Override
	public Stream<TopicStats> findAll() {
		return Stream.empty();
	}

	@Override
	public long count() {
		return -1L;
	}

	@Override
	public Optional<TopicStats> findOneByTopic(long topicId) {
		try {
			TopicStats ts = entityManager.createQuery("SELECT ts FROM TopicStats ts WHERE ts.topicId = ?1", TopicStats.class).setParameter(1, topicId).getSingleResult();
			return Optional.ofNullable(ts);
		}catch(javax.persistence.NoResultException e) {
			if(logger.isDebugEnabled()){
				logger.debug(e.getMessage(), e);
			}
		}
		return Optional.empty();
	}
	
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public Optional<Boolean> createStats(long topicId, int volumesId, long boardId) {
		try {
			entityManager.persist(new TopicStats(topicId, volumesId, boardId));
			return Optional.of(true);
		}catch(Exception e) {
			if(logger.isDebugEnabled()){
				logger.debug(e.getMessage(), e);
			}
		}
		return Optional.empty();
	}
	
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public Optional<Boolean> updatePosts(
			long topicId, 
			long recentPostsMemberId, 
			String recentPostsMemberNickname,
			LocalDateTime recentPostsDate, 
			long recentPostsId) {
		try {
			int tsAffect = entityManager.createQuery("UPDATE TopicStats ts SET ts.postses = ts.postses + 1, ts.recentPostsMemberId = ?1, ts.recentPostsMemberNickname = ?2, ts.recentPostsDate = ?3, ts.updateDate = ?4, ts.recentPostsId = ?5 WHERE ts.topicId = ?6")
					.setParameter(1, recentPostsMemberId)
					.setParameter(2, recentPostsMemberNickname)
					.setParameter(3, recentPostsDate)
					.setParameter(4, LocalDateTime.now())
					.setParameter(5, recentPostsId)
					.setParameter(6, topicId)
					.executeUpdate();
			int tAffect = entityManager.createQuery("UPDATE Topic t SET t.rankingDateTime = ?1 WHERE t.id = ?2").setParameter(1, recentPostsDate).setParameter(2, topicId).executeUpdate();
			return (tsAffect == 1 && tsAffect == tAffect)?Optional.of(true):Optional.empty();
		}catch(Exception e) {
			if(logger.isDebugEnabled()){
				logger.debug(e.getMessage(), e);
			}
		}
		return Optional.empty();
	}
	
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public Optional<Boolean> plusFavorites(long topicId, long memberId) {
		try{
			int affect = entityManager.createQuery("UPDATE TopicStats ts SET ts.favorites = ts.favorites + 1, ts.updateDate = ?1 WHERE ts.topicId = ?2")
					.setParameter(1, LocalDateTime.now())
					.setParameter(2, topicId)
					.executeUpdate();
			try{
				//为下次取消收藏清路
				entityManager.createNativeQuery("DELETE FROM apo_action_event_set WHERE `TYPE` = ?1 AND `ACTION` = ?2 AND MEMBERID = ?3 AND TOPICID = ?4")
					.setParameter(1, "T")
					.setParameter(2, "TOPIC_FAVORITE_CANCEL")
					.setParameter(3, memberId)
					.setParameter(4, topicId)
					.executeUpdate();
			}catch(Exception e){
				logger.info("[TopicStatsDao]favorite plus has exception:"+e.getMessage());
			}
			return affect == 1?Optional.of(true):Optional.empty();
		}catch(Exception e) {
			if(logger.isDebugEnabled()){
				logger.debug(e.getMessage(), e);
			}
		}
		return Optional.empty();
	}
	
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public Optional<Boolean> negateFavorites(long topicId, long memberId) {
		try{
			int affect = entityManager.createQuery("UPDATE TopicStats ts SET ts.favorites = ts.favorites - 1, ts.updateDate = ?1 WHERE ts.topicId = ?2")
					.setParameter(1, LocalDateTime.now())
					.setParameter(2, topicId)
					.executeUpdate();
			try{
				//为下次收藏清路
				entityManager.createNativeQuery("DELETE FROM apo_action_event_set WHERE `TYPE` = ?1 AND `ACTION` = ?2 AND MEMBERID = ?3 AND TOPICID = ?4")
					.setParameter(1, "T")
					.setParameter(2, "TOPIC_FAVORITE")
					.setParameter(3, memberId)
					.setParameter(4, topicId)
					.executeUpdate();
			}catch(Exception e){
				logger.info("[TopicStatsDao]favorite negate has exception:"+e.getMessage());
			}
			return affect == 1?Optional.of(true):Optional.empty();
		}catch(Exception e) {
			if(logger.isDebugEnabled()){
				logger.debug(e.getMessage(), e);
			}
		}
		return Optional.empty();
	}

	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public Optional<Boolean> plusLikes(long topicId, long memberId) {
		try{
			int affect = entityManager.createQuery("UPDATE TopicStats ts SET ts.likes = ts.likes + 1, ts.updateDate = ?1 WHERE ts.topicId = ?2")
					.setParameter(1, LocalDateTime.now())
					.setParameter(2, topicId)
					.executeUpdate();
			try{
				//为下次取消点赞清路
				entityManager.createNativeQuery("DELETE FROM apo_action_event_set WHERE `TYPE` = ?1 AND `ACTION` = ?2 AND MEMBERID = ?3 AND TOPICID = ?4")
					.setParameter(1, "T")
					.setParameter(2, "TOPIC_LIKED_CANCEL")
					.setParameter(3, memberId)
					.setParameter(4, topicId)
					.executeUpdate();
			}catch(Exception e){
				logger.info("[TopicStatsDao]like plus has exception:"+e.getMessage());
			}
			return affect == 1?Optional.of(true):Optional.empty();
		}catch(Exception e) {
			if(logger.isDebugEnabled()){
				logger.debug(e.getMessage(), e);
			}
		}
		return Optional.empty();
	}
	
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public Optional<Boolean> negateLikes(long topicId, long memberId) {
		try{
			int affect = entityManager.createQuery("UPDATE TopicStats ts SET ts.likes = ts.likes - 1, ts.updateDate = ?1 WHERE ts.topicId = ?2")
					.setParameter(1, LocalDateTime.now())
					.setParameter(2, topicId)
					.executeUpdate();
			try{
				//为下次点赞清路
				entityManager.createNativeQuery("DELETE FROM apo_action_event_set WHERE `TYPE` = ?1 AND `ACTION` = ?2 AND MEMBERID = ?3 AND TOPICID = ?4")
					.setParameter(1, "T")
					.setParameter(2, "TOPIC_LIKED")
					.setParameter(3, memberId)
					.setParameter(4, topicId)
					.executeUpdate();
			}catch(Exception e){
				logger.info("[TopicStatsDao]like negate has exception:"+e.getMessage());
			}
			return affect == 1?Optional.of(true):Optional.empty();
		}catch(Exception e) {
			if(logger.isDebugEnabled()){
				logger.debug(e.getMessage(), e);
			}
		}
		return Optional.empty();
	}

	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public Optional<Boolean> updateDisplaies(long topicId) {
		//是否达到火贴的标准了
		TopicStats ts = findOneByTopic(topicId).orElse(null);
		if(null == ts){
			return Optional.empty();
		}
		if(ts.getDisplaies() > 300){
			entityManager.createQuery("UPDATE Topic t SET t.hots = ?1 WHERE t.hots = ?2 AND t.id = ?3").setParameter(1, true).setParameter(2, false).setParameter(3, topicId).executeUpdate();
		}
		try{
			ts.setDisplaies(ts.getDisplaies()+1);
			ts.setUpdateDate(LocalDateTime.now());
			entityManager.merge(ts);
			return Optional.of(true);
		} catch (Exception e) {
			if(logger.isDebugEnabled()){
				logger.debug(e.getMessage(), e);
			}
		}
		return Optional.empty();
	}

	@Override
	public Stream<TopicStats> findAllByTopicId(Collection<Long> topicIdList) {
		if(topicIdList == null || topicIdList.isEmpty()){
			return Stream.empty();
		}
		return entityManager.createQuery("SELECT ts FROM TopicStats ts WHERE ts.topicId IN ?1", TopicStats.class).setParameter(1, topicIdList).getResultStream();
	}

	@Override
	public Stream<TopicStats> findAllByReplyDate(int size) {
		return entityManager.createQuery("SELECT ts FROM TopicStats ts ORDER BY ts.updateDate DESC", TopicStats.class).setMaxResults(size).getResultStream();
	}

}
