package com.red.circle.other.infra.database.mongo.service.live.impl;

import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.other.infra.database.mongo.entity.live.RoomUserBlacklist;
import com.red.circle.other.infra.database.mongo.service.live.RoomUserBlacklistService;
import com.red.circle.other.inner.model.cmd.live.RoomBlacklistQryCmd;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.sql.Timestamp;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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 org.springframework.stereotype.Service;

/**
 * @author houyong on 2020/12/03
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class RoomUserBlacklistServiceImpl implements RoomUserBlacklistService {

  private final MongoTemplate mongoTemplate;

  @Override
  public void add(RoomUserBlacklist roomUserBlacklist) {
    roomUserBlacklist.generatorId();
    if (Objects.isNull(roomUserBlacklist.getCreateTime())) {
      roomUserBlacklist.setCreateTime(TimestampUtils.now());
    }
    mongoTemplate.save(roomUserBlacklist);
  }

  @Override
  public List<RoomUserBlacklist> listBlacklist(Long roomId, Long lastId, Integer limit) {
    Criteria criteria = Criteria.where("roomId").is(roomId);

    if (Objects.nonNull(lastId)) {
      criteria.and("timingId").lt(lastId);
    }

    Query mongoQuery = Query.query(criteria).with(Sort.by(Sort.Order.desc("timingId")))
        .limit(PageConstant.limitSizeStrict(limit));
    return mongoTemplate.find(mongoQuery, RoomUserBlacklist.class);
  }

  @Override
  public List<RoomUserBlacklist> listOps(RoomBlacklistQryCmd qryCmd) {
    Criteria criteria = new Criteria();

    if (Objects.nonNull(qryCmd.getRoomId())) {

      criteria.and("roomId").is(qryCmd.getRoomId());
    }

    if (Objects.nonNull(qryCmd.getUserId())) {
      criteria.and("userId").is(qryCmd.getUserId());
    }

    if (Objects.nonNull(qryCmd.getLastId())) {
      criteria.and("timingId").lt(qryCmd.getLastId());
    }

    if (Objects.nonNull(qryCmd.getCreateUserId())) {
      criteria.and("createUser").is(qryCmd.getCreateUserId());
    }

    if (StringUtils.isNotBlank(qryCmd.getSysOrigin())) {
      criteria.and("sysOrigin").is(qryCmd.getSysOrigin());
    }

    if (Objects.nonNull(qryCmd.getStartTime()) && Objects.nonNull(qryCmd.getEndTime())) {
      criteria.andOperator(
          Criteria.where("createTime").gte(new Timestamp(qryCmd.getStartTime())),
          Criteria.where("createTime").lte(new Timestamp(qryCmd.getEndTime()))
      );
    } else if (Objects.nonNull(qryCmd.getStartTime())) {
      criteria.and("createTime").gte(new Timestamp(qryCmd.getStartTime()));
    } else if (Objects.nonNull(qryCmd.getEndTime())) {
      criteria.and("createTime").lte(new Timestamp(qryCmd.getEndTime()));
    }

    Query mongoQuery = Query.query(criteria).with(Sort.by(Sort.Order.desc("timingId")))
        .limit(PageConstant.limitSizeStrict(qryCmd.getSize()));
    return mongoTemplate.find(mongoQuery, RoomUserBlacklist.class);
  }

  @Override
  public void removeBlack(Long roomId, Long userId) {
    Criteria criteria = Criteria.where("roomId").is(roomId).and("userId").is(userId);
    mongoTemplate.remove(Query.query(criteria), RoomUserBlacklist.class);
  }

  @Override
  public Boolean exists(Long roomId, Long userId) {
    Criteria criteria = Criteria.where("userId").is(userId).and("roomId").is(roomId);
    Query query = Query.query(criteria).limit(1);
    return Optional.ofNullable(mongoTemplate.findOne(query, RoomUserBlacklist.class))
        .map(roomUserBlacklist -> Objects.nonNull(roomUserBlacklist.getId()))
        .orElse(Boolean.FALSE);
  }
  @Override
  public List<RoomUserBlacklist> getBlackRoom(Long cmdOriginUserId, Set<Long> roomIds) {
    Criteria criteria = Criteria.where("userId").is(cmdOriginUserId).and("roomId").in(roomIds);
    Query mongoQuery = Query.query(criteria).with(Sort.by(Sort.Order.desc("timingId")))
            .limit(100);
    return mongoTemplate.find(mongoQuery, RoomUserBlacklist.class);
  }
}
