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

import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
import com.red.circle.other.infra.database.rds.dao.activity.ActivityReceiveRewardLogDAO;
import com.red.circle.other.infra.database.rds.entity.activity.ActivityReceiveRewardLog;
import com.red.circle.other.infra.database.rds.service.activity.ActivityReceiveRewardLogService;
import com.red.circle.other.inner.enums.activity.PropsActivityTypeEnum;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.LocalDateUtils;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 周星奖励日志 服务实现类.
 * </p>
 *
 * @author pengliang
 * @since 2021-06-23
 */
@Service
public class ActivityReceiveRewardLogServiceImpl extends
    BaseServiceImpl<ActivityReceiveRewardLogDAO, ActivityReceiveRewardLog> implements
    ActivityReceiveRewardLogService {

  @Override
  public boolean existsThisWeek(Long userId, PropsActivityTypeEnum activityType) {
    return Optional.ofNullable(
            query()
                .select(ActivityReceiveRewardLog::getId)
                .eq(ActivityReceiveRewardLog::getUserId, userId)
                .eq(ActivityReceiveRewardLog::getType, activityType)
                .ge(ActivityReceiveRewardLog::getCreateTime, LocalDateUtils.nowWeekMonday())
                .last(PageConstant.LIMIT_ONE)
                .getOne())
        .map(activityReceiveRewardLog -> Objects.nonNull(activityReceiveRewardLog.getId()))
        .orElse(Boolean.FALSE);
  }

  @Override
  public boolean existsThisWeek(Long userId, Long receiveId, PropsActivityTypeEnum activityType) {
    return Optional.ofNullable(
            query()
                .select(ActivityReceiveRewardLog::getId)
                .eq(ActivityReceiveRewardLog::getUserId, userId)
                .eq(ActivityReceiveRewardLog::getType, activityType)
                .eq(ActivityReceiveRewardLog::getReceiveId, receiveId)
                .ge(ActivityReceiveRewardLog::getCreateTime, LocalDateUtils.nowWeekMonday())
                .last(PageConstant.LIMIT_ONE)
                .getOne())
        .map(activityReceiveRewardLog -> Objects.nonNull(activityReceiveRewardLog.getId()))
        .orElse(Boolean.FALSE);
  }

  @Override
  public boolean existsThisMonth(Long userId, Long receiveId, PropsActivityTypeEnum activityType) {
    return Optional.ofNullable(
            query()
                .select(ActivityReceiveRewardLog::getId)
                .eq(ActivityReceiveRewardLog::getUserId, userId)
                .eq(ActivityReceiveRewardLog::getType, activityType)
                .eq(ActivityReceiveRewardLog::getReceiveId, receiveId)
                .ge(ActivityReceiveRewardLog::getCreateTime, LocalDateUtils.nowFirstDayOfMonth())
                .last(PageConstant.LIMIT_ONE)
                .getOne())
        .map(activityReceiveRewardLog -> Objects.nonNull(activityReceiveRewardLog.getId()))
        .orElse(Boolean.FALSE);
  }

  @Override
  public boolean existsThisNow(Long userId, Long receiveId, PropsActivityTypeEnum activityType) {
    return Optional.ofNullable(
            query()
                .select(ActivityReceiveRewardLog::getId)
                .eq(ActivityReceiveRewardLog::getUserId, userId)
                .eq(ActivityReceiveRewardLog::getType, activityType)
                .eq(ActivityReceiveRewardLog::getReceiveId, receiveId)
                .ge(ActivityReceiveRewardLog::getCreateTime, LocalDate.now())
                .last(PageConstant.LIMIT_ONE)
                .getOne())
        .map(activityReceiveRewardLog -> Objects.nonNull(activityReceiveRewardLog.getId()))
        .orElse(Boolean.FALSE);
  }

  @Override
  public boolean exists(Long userId, Long receiveId, PropsActivityTypeEnum activityType) {
    return Optional.ofNullable(
            query()
                .select(ActivityReceiveRewardLog::getId)
                .eq(ActivityReceiveRewardLog::getUserId, userId)
                .eq(ActivityReceiveRewardLog::getReceiveId, receiveId)
                .eq(ActivityReceiveRewardLog::getType, activityType)
                .last(PageConstant.LIMIT_ONE)
                .getOne())
        .map(activityReceiveRewardLog -> Objects.nonNull(activityReceiveRewardLog.getId()))
        .orElse(Boolean.FALSE);
  }

  @Override
  public List<Long> getReceivedIds(Long userId, PropsActivityTypeEnum activityType) {
    return Optional.ofNullable(query()
            .select(ActivityReceiveRewardLog::getReceiveId)
            .eq(ActivityReceiveRewardLog::getUserId, userId)
            .eq(ActivityReceiveRewardLog::getType, activityType)
            .last(PageConstant.formatLimit(100))
            .list())
        .map(activityReceiveRewardLogs -> activityReceiveRewardLogs.stream()
            .map(ActivityReceiveRewardLog::getReceiveId)
            .collect(Collectors.toList()))
        .orElse(CollectionUtils.newArrayList());
  }

  @Override
  public Map<Long, ActivityReceiveRewardLog> mapByReceiveId(Long userId,
      PropsActivityTypeEnum activityType, Set<Long> ids) {
    return CollectionUtils.isNotEmpty(ids)
        ? Optional.ofNullable(
            query()
                .eq(ActivityReceiveRewardLog::getUserId, userId)
                .eq(ActivityReceiveRewardLog::getType, activityType)
                .in(ActivityReceiveRewardLog::getReceiveId, ids)
                .list())
        .map(activityReceiveRewardLogs ->
            activityReceiveRewardLogs.stream()
                .collect(Collectors.toMap(ActivityReceiveRewardLog::getReceiveId,
                    Function.identity(), (k, v) -> v)))
        .orElseGet(CollectionUtils::newHashMap)
        : CollectionUtils.newHashMap();
  }

  @Override
  public Map<Long, ActivityReceiveRewardLog> mapThisMonthByReceiveId(Long userId,
      PropsActivityTypeEnum activityType, Set<Long> ids) {
    return CollectionUtils.isNotEmpty(ids)
        ? Optional.ofNullable(
            query()
                .ge(ActivityReceiveRewardLog::getCreateTime,
                    LocalDateUtils.nowFirstDayOfMonth())
                .eq(ActivityReceiveRewardLog::getUserId, userId)
                .eq(ActivityReceiveRewardLog::getType, activityType)
                .in(ActivityReceiveRewardLog::getReceiveId, ids)
                .list())
        .map(activityReceiveRewardLogs ->
            activityReceiveRewardLogs.stream()
                .collect(Collectors.toMap(ActivityReceiveRewardLog::getReceiveId,
                    Function.identity(), (k, v) -> v)))
        .orElseGet(CollectionUtils::newHashMap)
        : CollectionUtils.newHashMap();
  }

}
