package com.red.circle.console.app.service.app.user;

import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.red.circle.console.app.convertor.sys.GiftAppConvertor;
import com.red.circle.console.app.dto.clienobject.user.GiftGiveRunningWaterCO;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.other.inner.endpoint.live.RoomManagerClient;
import com.red.circle.other.inner.endpoint.material.gift.GiftGiveRunningWaterClient;
import com.red.circle.other.inner.model.cmd.gift.GiftGiveRunningWaterBackQryCmd;
import com.red.circle.other.inner.model.dto.gift.GiftAcceptUserDTO;
import com.red.circle.other.inner.model.dto.gift.GiftGiveRunningWaterDTO;
import com.red.circle.other.inner.model.dto.live.RoomProfileDTO;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.other.inner.endpoint.user.user.UserProfileClient;
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;

/**
 * <p>
 * 用户扩展信息 服务实现类
 * </p>
 *
 * @author pengliang
 * @since 2019-11-08
 */

@Service
@RequiredArgsConstructor
public class RunningWaterServiceImpl implements
    RunningWaterLogService {

  private final GiftAppConvertor giftAppConvertor;
  private final RoomManagerClient roomManagerClient;
  private final UserProfileClient userProfileClient;
  private final GiftGiveRunningWaterClient giftGiveRunningWaterClient;


  @Override
  public List<GiftGiveRunningWaterCO> listGiftGiveRunningWater(
      GiftGiveRunningWaterBackQryCmd query) {
    List<GiftGiveRunningWaterDTO> giftGiveRunningWaters = ResponseAssert.requiredSuccess(
        giftGiveRunningWaterClient.listGiftGiveRunningWater(query));

    Map<Long, UserProfileDTO> userProfileMap = ResponseAssert.requiredSuccess(
        userProfileClient.mapByUserIds(
            getAllUserIds(giftGiveRunningWaters)));
    return giftGiveRunningWaters.stream().map(giftGiveRunningWater -> {
      GiftGiveRunningWaterCO co = giftAppConvertor.toGiftGiveRunningWaterCO(giftGiveRunningWater);
      co.setUserProfile(userProfileMap.get(giftGiveRunningWater.getUserId()));

      co.getAcceptUsers().forEach(accept -> accept.setUserProfile(
          userProfileMap.get(accept.getAcceptUserId())));
      return co;
    }).toList();
  }

  @Override
  public List<GiftGiveRunningWaterCO> listUserRoomGiftGiveRunningWater(Long userId, Long lastId) {

    RoomProfileDTO roomProfile = ResponseAssert.requiredSuccess(
        roomManagerClient.getProfileByUserId(userId));
    if (Objects.isNull(roomProfile)) {
      return Lists.newArrayList();
    }
    GiftGiveRunningWaterBackQryCmd query = new GiftGiveRunningWaterBackQryCmd();
    query.setOriginId(roomProfile.getId().toString());
    query.setLastId(lastId);
    List<GiftGiveRunningWaterDTO> giftGiveRunningWaters = ResponseAssert.requiredSuccess(
        giftGiveRunningWaterClient.listGiftGiveRunningWater(query));

    Map<Long, UserProfileDTO> userProfileMap = ResponseAssert.requiredSuccess(
        userProfileClient.mapByUserIds(
            getAllUserIds(giftGiveRunningWaters)));
    return giftGiveRunningWaters.stream().map(giftGiveRunningWater -> {
      GiftGiveRunningWaterCO co = giftAppConvertor.toGiftGiveRunningWaterCO(giftGiveRunningWater);
      co.setUserProfile(userProfileMap.get(giftGiveRunningWater.getUserId()));

      co.getAcceptUsers().forEach(accept -> accept.setUserProfile(
          userProfileMap.get(accept.getAcceptUserId())));
      return co;
    }).toList();
  }

  @Override
  public String getGiftGiveRunningWaterCount(GiftGiveRunningWaterBackQryCmd query) {
    return ResponseAssert.requiredSuccess(
        giftGiveRunningWaterClient.sumGiftValue(query));
  }

  @Override
  public String getAcceptGiftQuantity(GiftGiveRunningWaterBackQryCmd query) {
    return ResponseAssert.requiredSuccess(giftGiveRunningWaterClient.sumGiftQuantity(query));
  }


  private Set<Long> getAllUserIds(List<GiftGiveRunningWaterDTO> runningWaters) {
    Set<Long> acceptUserIds = runningWaters.stream().map(GiftGiveRunningWaterDTO::getAcceptUsers)
        .flatMap(Collection::stream)
        .map(GiftAcceptUserDTO::getAcceptUserId)
        .collect(Collectors.toSet());
    Set<Long> sendUserIds = runningWaters.stream().map(GiftGiveRunningWaterDTO::getUserId)
        .collect(Collectors.toSet());
    acceptUserIds.addAll(sendUserIds);
    return acceptUserIds;
  }
}
