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

import com.mongodb.client.model.Filters;
import com.red.circle.component.mongodb.config.MongoPrimaryService;
import com.red.circle.other.infra.database.mongo.entity.activity.RoomFanVotesActivityCount;
import com.red.circle.other.infra.database.mongo.service.activity.RoomFanVotesActivityCountService;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.util.List;
import java.util.Objects;
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.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

/**
 * 房间粉丝人气票活动.
 *
 * @author pengshigang on 2023/6/9
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RoomFanVotesActivityCountServiceImpl implements RoomFanVotesActivityCountService {

  private final MongoTemplate mongoTemplate;
  private final MongoPrimaryService mongoPrimaryService;

  @Override
  public void incr(Long roomId, Long userId, String regionCode, Long points) {

    if (points <= 0 || StringUtils.isBlank(regionCode) || Objects.isNull(roomId)) {
      return;
    }

    String id = getUnpaid(roomId);

    if (existsPrimaryUnpaid(id)) {

      mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(id)),
          new Update()
              .inc("points", points)
              .set("regionCode", regionCode)
          , RoomFanVotesActivityCount.class);
      return;
    }

    mongoTemplate.save(new RoomFanVotesActivityCount()
        .setId(id)
        .setRoomId(roomId)
        .setUserId(userId)
        .setPoints(points)
        .setRegionCode(regionCode)
        .setDel(Boolean.FALSE)
        .setHistory(Boolean.FALSE)
        .setAlreadySent(Boolean.FALSE)
        .setDateNumber(ZonedDateTimeAsiaRiyadhUtils.nowDateToInt())
        .setCreateTime(TimestampUtils.now())
        .setExpiredTime(TimestampUtils.nowPlusDays(30))
    );

  }

  @Override
  public RoomFanVotesActivityCount getByRoomId(Long roomId) {

    String id = roomId + "_" + ZonedDateTimeAsiaRiyadhUtils.nowDateToInt();
    return mongoTemplate
        .findOne(Query.query(Criteria.where("id").is(id)), RoomFanVotesActivityCount.class);
  }

  @Override
  public List<RoomFanVotesActivityCount> listHistory(String regionCode) {

    return mongoTemplate.find(Query.query(Criteria.where("regionCode").is(regionCode)
            .and("del").is(Boolean.FALSE)
            .and("history").is(Boolean.TRUE))
        .with(Sort.by(Sort.Order.desc("points")))
        .limit(10), RoomFanVotesActivityCount.class);

  }

  @Override
  public List<RoomFanVotesActivityCount> listCurrent(String regionCode, Integer limit) {

    return mongoTemplate.find(Query.query(Criteria.where("regionCode").is(regionCode)
                .and("del").is(Boolean.FALSE)
                .and("history").is(Boolean.FALSE))
            .with(Sort.by(Sort.Order.desc("points")))
            .limit(limit)
        , RoomFanVotesActivityCount.class);
  }

  @Override
  public List<RoomFanVotesActivityCount> listCurrent(String regionCode, String sysOrigin,
      Integer limit) {

    return mongoTemplate.find(Query.query(Criteria.where("regionCode").is(regionCode)
                .and("del").is(Boolean.FALSE)
                .and("sysOrigin").is(sysOrigin)
                .and("history").is(Boolean.FALSE))
            .with(Sort.by(Sort.Order.desc("points")))
            .limit(limit)
        , RoomFanVotesActivityCount.class);
  }

  @Override
  public void upHistory(List<String> regionCodes) {

    // 小于今天的数据全部修改为历史
    mongoTemplate.updateMulti(Query.query(Criteria.where("regionCode").in(regionCodes)
            .and("dateNumber").lt(ZonedDateTimeAsiaRiyadhUtils.nowDateToInt())
            .and("history").is(Boolean.FALSE)),
        new Update().set("history", Boolean.TRUE), RoomFanVotesActivityCount.class);

  }

  @Override
  public void upAlreadySent(String regionCode) {

    mongoTemplate.updateMulti(Query.query(Criteria.where("regionCode").is(regionCode)
            .and("del").is(Boolean.FALSE)
            .and("alreadySent").is(Boolean.FALSE)),
        new Update().set("alreadySent", Boolean.TRUE), RoomFanVotesActivityCount.class);
  }

  @Override
  public void del(List<String> regionCodes) {

    // 小于昨天的全部删除
    mongoTemplate.updateMulti(Query.query(Criteria.where("regionCode").in(regionCodes)
            .and("dateNumber").lt(ZonedDateTimeAsiaRiyadhUtils.nowMinusDaysToDateInt(1))
            .and("del").is(Boolean.FALSE)),
        new Update().set("del", Boolean.TRUE), RoomFanVotesActivityCount.class);

  }

  private boolean existsPrimaryUnpaid(String id) {

    return mongoPrimaryService.exists("room_fan_votes_activity_count",
        Filters.eq("_id", id)
    );
  }

  private String getUnpaid(Long roomId) {
    return roomId + "_" + ZonedDateTimeAsiaRiyadhUtils.nowDateToInt();
  }

}
