package com.red.circle.game.fruit.infrastructure.database.repository.impl;

import com.red.circle.common.business.dto.cmd.PageUserIdCmd;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
import com.red.circle.game.fruit.application.dto.clientobject.GameFruitAwardRecordCO;
import com.red.circle.game.fruit.application.dto.cmd.UserBetCmd;
import com.red.circle.game.fruit.infrastructure.database.dao.DaysRankingDAO;
import com.red.circle.game.fruit.infrastructure.database.entity.GameFruitUserDaysRanking;
import com.red.circle.game.fruit.infrastructure.database.repository.GameFruitUserDaysRankingService;
import com.red.circle.tool.core.date.DateFormatConstant;
import com.red.circle.tool.core.date.DateUtils;
import com.red.circle.tool.core.date.LocalDateUtils;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 用户每日盈利排名 服务实现类.
 * </p>
 *
 * @author lisizhe on 2023-11-30 19:17
 */
@Service
@RequiredArgsConstructor
public class GameFruitUserDaysRankingServiceImpl extends
    BaseServiceImpl<DaysRankingDAO, GameFruitUserDaysRanking> implements
    GameFruitUserDaysRankingService {

  @Override
  public List<GameFruitUserDaysRanking> listTop10(Integer top, String origin) {
    return query().eq(GameFruitUserDaysRanking::getDate, LocalDateUtils.nowToInteger())
        .eq(GameFruitUserDaysRanking::getSysOrigin, origin)
        .gt(GameFruitUserDaysRanking::getEarning, BigDecimal.ZERO)
        .orderByDesc(GameFruitUserDaysRanking::getEarning).last(PageConstant.formatLimit(top))
        .list();
  }

  @Override
  public GameFruitUserDaysRanking getUserEarning(Long userId) {
    return query()
        .eq(GameFruitUserDaysRanking::getUserId, userId)
        .eq(GameFruitUserDaysRanking::getDate, LocalDateUtils.nowToInteger().toString())
        .orderByDesc(GameFruitUserDaysRanking::getEarning)
        .last(PageConstant.LIMIT_ONE).getOne();
  }

  @Override
  public void addDaysRankingBet(UserBetCmd cmd) {
    GameFruitUserDaysRanking gameFruitUserDaysRanking = baseDAO.getByUidForUpdate(cmd.getUid(),
        LocalDateUtils.nowToInteger().toString());
    if (Objects.isNull(gameFruitUserDaysRanking)) {
      save(
          new GameFruitUserDaysRanking()
              .setBetAmount(cmd.getSumAmount())
              .setSysOrigin(cmd.getSysOrigin())
              .setBetSize(1)
              .setDate(LocalDateUtils.nowToInteger().toString())
              .setUserId(cmd.getUid())
              .setEarning(BigDecimal.ZERO)
      );
      return;
    }
    update()
        .set(GameFruitUserDaysRanking::getBetAmount,
            gameFruitUserDaysRanking.getBetAmount().add(cmd.getSumAmount()))
        .set(GameFruitUserDaysRanking::getBetSize, gameFruitUserDaysRanking.getBetSize() + 1)
        .eq(GameFruitUserDaysRanking::getUserId, gameFruitUserDaysRanking.getUserId())
        .eq(GameFruitUserDaysRanking::getDate, LocalDateUtils.nowToInteger().toString())
        .execute();
  }

  @Override
  public void addDaysRankingEarning(List<GameFruitAwardRecordCO> gameFruitAwardRecords) {
    baseDAO.addDaysRankingEarning(gameFruitAwardRecords);
  }

  @Override
  public List<GameFruitUserDaysRanking> listByUserIds(Set<Long> userIds,
      BigDecimal lossRatioLottery,
      BigDecimal toDayLossLottery) {
    return baseDAO.listByUserIds(userIds, lossRatioLottery, toDayLossLottery);
  }

  @Override
  public Long countWeekEarning(Long userId) {
    Date startDate = DateUtils.setDateTime(DateUtils.nowMonday(), 0, 0, 0);
    Date endDate = DateUtils.setDateTime(DateUtils.nowSunday(), 23, 59, 59);
    return Optional.ofNullable(baseDAO.countWeekEarning(userId, startDate, endDate)).orElse(0L);
  }

  @Override
  public Long countWeekPlayDays(Long userId) {
    Date startDate = DateUtils.setDateTime(DateUtils.nowMonday(), 0, 0, 0);
    Date endDate = DateUtils.setDateTime(DateUtils.nowSunday(), 23, 59, 59);
    return Optional.ofNullable(baseDAO.countWeekPlayDays(userId, startDate, endDate)).orElse(0L);
  }

  @Override
  public List<GameFruitUserDaysRanking> getTopLimit(Long quantity, String sysOrigin) {
    return query().eq(GameFruitUserDaysRanking::getDate,
            DateUtils.formatUtc(DateUtils.nowMinusDays(1), DateFormatConstant.yyyyMMdd))
        .eq(GameFruitUserDaysRanking::getSysOrigin, sysOrigin)
        .orderByDesc(GameFruitUserDaysRanking::getEarning)
        .last(PageConstant.formatLimit(quantity.intValue()))
        .list();
  }

  @Override
  public PageResult<GameFruitUserDaysRanking> pageDaysUserData(PageUserIdCmd cmd) {
    return query().eq(Objects.nonNull(cmd.getUserId()), GameFruitUserDaysRanking::getUserId,
            cmd.getUserId())
        .orderByDesc(GameFruitUserDaysRanking::getDate)
        .orderByDesc(GameFruitUserDaysRanking::getEarning)
        .page(cmd.getPageQuery());
  }
}
