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.enums.VipAbilityType;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.infra.database.cache.service.other.EnumConfigCacheService;
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.infra.utils.UserIdEncryptUtils;
import com.red.circle.other.inner.enums.config.EnumConfigKey;
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.*;
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 GiftsReceivedLeaderboardQryExe {

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

  public ActivityLeaderboardCO execute(AppExtCommand cmd) {
    List<RankQueenCount> hours = getListRank(cmd, RankQueenType.CHARM_RANK_HOUR,50);
    List<RankQueenCount> days = getListRank(cmd, RankQueenType.CHARM_RANK_DAY,50);
    List<RankQueenCount> weeks = getListRank(cmd, RankQueenType.CHARM_RANK_WEEK,50);
    List<RankQueenCount> months = getListRank(cmd, RankQueenType.CHARM_RANK_MONTH,50);

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

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

  public ActivityLeaderboardCO executeApp(AppExtCommand cmd) {
//    List<RankQueenCount> hours = getListRank(cmd, RankQueenType.CHARM_RANK_HOUR,3);
//    List<RankQueenCount> days = getListRank(cmd, RankQueenType.CHARM_RANK_DAY,3);
    List<RankQueenCount> weeks = getListRank(cmd, RankQueenType.CHARM_RANK_WEEK,3);
//    List<RankQueenCount> months = getListRank(cmd, RankQueenType.CHARM_RANK_MONTH,3);

    Set<Long> userIds = getUserIds(weeks);
//    userIds.addAll(getUserIds(days));
//    userIds.addAll(getUserIds(months));
//    userIds.addAll(getUserIds(hours));
    if (CollectionUtils.isEmpty(userIds)) {
      return ActivityLeaderboardCO.empty();
    }
    Map<Long, UserProfileDTO> userProfileMap = userProfileAppConvertor.toMapUserProfileDTO(
            userProfileGateway.mapByUserIds(userIds)
    );
    Set<Long> invisibleUserIds = userProfileGateway.filterUsersByVipAbility(userIds, VipAbilityType.MYSTERIOUS_INVISIBILITY);

    List<RankQueenCount> emptyList = Collections.emptyList();
    return new ActivityLeaderboardCO()
            .setHourly(toLeaderboardUserCO(emptyList, userProfileMap, invisibleUserIds))
            .setDaily(toLeaderboardUserCO(emptyList, userProfileMap, invisibleUserIds))
            .setWeekly(toLeaderboardUserCO(weeks, userProfileMap, invisibleUserIds))
            .setMonthly(toLeaderboardUserCO(emptyList, userProfileMap, invisibleUserIds))
            ;
  }


  private List<LeaderboardUserCO> toLeaderboardUserCO(List<RankQueenCount> list,
      Map<Long, UserProfileDTO> userProfileMap, Set<Long> invisibleUserIds) {
    return list.stream().map(count -> {
      UserProfileDTO userProfile = userProfileMap.get(count.getBusinessId());
      if (Objects.isNull(userProfile)) {
        log.warn("数据错误，没有找到用户记录: {}", JacksonUtils.toJson(count));
        return null;
      }
      LeaderboardUserCO co = new LeaderboardUserCO()
          .setQuantity(count.getQuantity())
          .setQuantityFormat(NumUtils.formatLong(count.getQuantity()));
      if (invisibleUserIds.contains(count.getBusinessId())) {
        co.setId(null);
        co.setEncryptedId(UserIdEncryptUtils.encrypt(userProfile.getId()));
        co.setNickname("****");
        co.setAvatar(enumConfigCacheService.getValue(EnumConfigKey.USER_YINSHEN_COVER, userProfile.getSysOriginChild()));
      } else {
        co.setId(userProfile.getId());
        co.setAvatar(userProfile.getUserAvatar());
        co.setNickname(userProfile.getUserNickname());
      }
      return co;
    }).filter(Objects::nonNull).collect(Collectors.toList());
  }


  private Set<Long> getUserIds(List<RankQueenCount> days) {
    return days.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);
  }


}
