package com.red.circle.other.app.command.activity;

import com.red.circle.common.business.dto.cmd.AppExtCommand;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.dto.clientobject.activity.ActivityLeaderboardCO;
import com.red.circle.other.app.dto.clientobject.activity.ActivityLeaderboardCO.LeaderboardUserCO;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.infra.database.mongo.entity.activity.RankQueenCount;
import com.red.circle.other.infra.database.mongo.entity.activity.RankQueenType;
import com.red.circle.other.infra.database.mongo.service.activity.RankCountService;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.json.JacksonUtils;
import com.red.circle.tool.core.num.NumUtils;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 礼物赠送排行榜.
 *
 * @author pengliang on 2021/2/24
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class GiftsSendLeaderboardQryExe {

  private final RankCountService rankCountService;
  private final UserProfileGateway userProfileGateway;
  private final UserProfileAppConvertor userProfileAppConvertor;

  public ActivityLeaderboardCO execute(AppExtCommand cmd) {
    List<RankQueenCount> hours = getListRank(cmd, RankQueenType.WEALTH_RANK_HOUR,50);
    List<RankQueenCount> days = getListRank(cmd, RankQueenType.WEALTH_RANK_DAY,50);
    List<RankQueenCount> weeks = getListRank(cmd, RankQueenType.WEALTH_RANK_WEEK,50);
    List<RankQueenCount> months = getListRank(cmd, RankQueenType.WEALTH_RANK_MONTH,50);

    Set<Long> userIds = getAllUserIds(days, weeks, months, hours);
    if (CollectionUtils.isEmpty(userIds)) {
      return ActivityLeaderboardCO.empty();
    }
    Map<Long, UserProfileDTO> userProfileMap = userProfileAppConvertor.toMapUserProfileDTO(
        userProfileGateway.mapByUserIds(userIds)
    );

    return new ActivityLeaderboardCO()
        .setHourly(toLeaderboardUserCO(hours, userProfileMap))
        .setDaily(toLeaderboardUserCO(days, userProfileMap))
        .setWeekly(toLeaderboardUserCO(weeks, userProfileMap))
        .setMonthly(toLeaderboardUserCO(months, userProfileMap));
  }

  public ActivityLeaderboardCO executeApp(AppExtCommand cmd) {

//    List<RankQueenCount> days = getListRank(cmd, RankQueenType.WEALTH_RANK_DAY,3);
    List<RankQueenCount> weeks = getListRank(cmd, RankQueenType.WEALTH_RANK_WEEK,3);
//    List<RankQueenCount> months = getListRank(cmd, RankQueenType.WEALTH_RANK_MONTH,3);

    Set<Long> userIds = getAllUserIds(null, weeks, null);
    if (CollectionUtils.isEmpty(userIds)) {
      return ActivityLeaderboardCO.empty();
    }
    Map<Long, UserProfileDTO> userProfileMap = userProfileAppConvertor.toMapUserProfileDTO(
            userProfileGateway.mapByUserIds(userIds)
    );

    return new ActivityLeaderboardCO()
            .setDaily(toLeaderboardUserCO(null, userProfileMap))
            .setWeekly(toLeaderboardUserCO(weeks, userProfileMap))
            .setMonthly(toLeaderboardUserCO(null, userProfileMap));
  }

  private Set<Long> getAllUserIds(List<RankQueenCount> days, List<RankQueenCount> weeks,
      List<RankQueenCount> months) {
    Set<Long> userIds = getUserIds(days);
    userIds.addAll(getUserIds(weeks));
    userIds.addAll(getUserIds(months));
    return userIds;
  }

  private Set<Long> getAllUserIds(List<RankQueenCount> days, List<RankQueenCount> weeks,
                                  List<RankQueenCount> months, List<RankQueenCount> hours) {
    Set<Long> userIds = getUserIds(days);
    userIds.addAll(getUserIds(weeks));
    userIds.addAll(getUserIds(months));
    userIds.addAll(getUserIds(hours));
    return userIds;
  }

  private List<LeaderboardUserCO> toLeaderboardUserCO(List<RankQueenCount> list,
      Map<Long, UserProfileDTO> userProfileMap) {
    if (CollectionUtils.isEmpty(list)) {
      return CollectionUtils.newArrayList();
    }
    return list.stream().map(count -> {
      UserProfileDTO userProfile = userProfileMap.get(count.getBusinessId());
      if (Objects.isNull(userProfile)) {
        log.warn("数据异常,找不到用户记录: {}", JacksonUtils.toJson(count));
        return null;
      }
      return new LeaderboardUserCO()
          .setId(userProfile.getId())
          .setAvatar(userProfile.getUserAvatar())
          .setNickname(userProfile.getUserNickname())
          .setQuantity(count.getQuantity())
          .setQuantityFormat(NumUtils.formatLong(count.getQuantity()));
    }).filter(Objects::nonNull).toList();
  }


  private Set<Long> getUserIds(List<RankQueenCount> counts) {
    if (CollectionUtils.isEmpty(counts)) {
      return CollectionUtils.newHashSet();
    }
    return counts.stream().map(RankQueenCount::getBusinessId)
        .collect(Collectors.toSet());
  }

  private List<RankQueenCount> getListRank(AppExtCommand cmd, RankQueenType charmRankDay,Integer size) {
    return Optional
        .ofNullable(rankCountService.listRank(cmd.requireReqSysOrigin(), charmRankDay, size))
        .orElseGet(CollectionUtils::newArrayList);
  }

}
