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

import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import com.red.circle.other.infra.common.user.UserCpUtils;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.dto.clientobject.activity.ActivityCpUserRankingCO;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.infra.database.mongo.entity.user.count.WeekCpValueCount;
import com.red.circle.other.infra.database.mongo.service.user.count.WeekCpValueCountService;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.other.inner.model.dto.user.WeekCpUserIdDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.num.NumUtils;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

/**
 * 每周CP用户礼物护送消耗.
 *
 * @author pengshigang on 2021/08/28
 * @since pengliang on 2022-03-25
 */
@Service
@RequiredArgsConstructor
public class LastWeekCpUsersTop3QueryExe {

  private final UserProfileGateway userProfileGateway;
  private final WeekCpValueCountService weekCpValueCountService;
  private final UserProfileAppConvertor userProfileAppConvertor;

  public List<ActivityCpUserRankingCO> execute(AppExtCommand cmd) {

    return assemble(weekCpValueCountService.listLastWeekTop(
        cmd.getReqSysOrigin().getOrigin(), 3)
    );
  }

  private List<ActivityCpUserRankingCO> assemble(
      List<WeekCpValueCount> weekCpValueCounts) {
    if (CollectionUtils.isEmpty(weekCpValueCounts)) {
      return Lists.newArrayList();
    }

    List<ActivityCpUserRankingCO> results = weekCpValueCounts.stream().map(weekCpValueCount -> {

          WeekCpUserIdDTO userIdPair = UserCpUtils.parseUserIdPair(weekCpValueCount.getId());

          return new ActivityCpUserRankingCO()
              .setUserId(userIdPair.getUserIdOne())
              .setCpUserId(userIdPair.getUserIdTwo())
              .setTotalNumber(weekCpValueCount.getQuantity())
              .setTotal(NumUtils.formatLong(weekCpValueCount.getQuantity()));
        }
    ).toList();

    Map<Long, UserProfileDTO> userProfileMap = getUserProfileMap(results);

    return results.stream().map(ranking -> {
          UserProfileDTO userProfile = userProfileMap.get(ranking.getUserId());
          UserProfileDTO cpUserProfile = userProfileMap.get(ranking.getCpUserId());
          if (Objects.isNull(userProfile) || Objects.isNull(cpUserProfile)) {
            return null;
          }

          ranking.setUserAvatar(userProfile.getUserAvatar());
          ranking.setUserNickname(userProfile.getUserNickname());
          ranking.setUserSex(userProfile.getUserSex());

          ranking.setCpUserAvatar(cpUserProfile.getUserAvatar());
          ranking.setCpUserNickname(cpUserProfile.getUserNickname());
          ranking.setCpUserSex(cpUserProfile.getUserSex());

          ranking.setUserProfiles(List.of(userProfile,
              cpUserProfile));
          return ranking;
        })
        .filter(Objects::nonNull)
        .toList();
  }

  private Map<Long, UserProfileDTO> getUserProfileMap(List<ActivityCpUserRankingCO> results) {
    return userProfileAppConvertor.toMapUserProfileDTO(
        userProfileGateway.mapByUserIds(
            getAllUserIds(results)
        )
    );
  }

  private Set<Long> getAllUserIds(List<ActivityCpUserRankingCO> results) {
    return results.stream()
        .map(ranking -> Arrays.asList(ranking.getUserId(), ranking.getCpUserId()))
        .flatMap(Collection::stream)
        .collect(Collectors.toSet());
  }


}
