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

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.red.circle.common.business.dto.cmd.app.AppUserIdCmd;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.dto.clientobject.pet.PetUserFriendCO;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.infra.database.rds.entity.pet.PetUserPetIncomeDetails;
import com.red.circle.other.infra.database.rds.service.pet.PetIncomeReceiveService;
import com.red.circle.other.infra.database.rds.service.pet.PetUserPetIncomeDetailsService;
import com.red.circle.other.infra.database.rds.service.user.user.RelationshipFriendService;
import com.red.circle.other.inner.model.dto.user.PetRelationshipFriendDTO;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
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.apache.commons.lang3.tuple.ImmutablePair;
import org.springframework.stereotype.Component;

/**
 * 宠物好友列表.
 *
 * @author pengliang on 2021/10/16
 */
@Component
@RequiredArgsConstructor
public class PetUserFriendQueryExe {

  private final UserProfileGateway userProfileGateway;
  private final UserProfileAppConvertor userProfileAppConvertor;
  private final PetIncomeReceiveService petIncomeReceiveService;
  private final RelationshipFriendService relationshipFriendService;
  private final PetUserPetIncomeDetailsService petUserPetIncomeDetailsService;

  public List<PetUserFriendCO> execute(AppUserIdCmd cmd) {

    List<PetRelationshipFriendDTO> petRelationshipFriends = relationshipFriendService.listPetBeanTop(
        cmd.getUserId(), 100);

    if (CollectionUtils.isEmpty(petRelationshipFriends)) {
      return Lists.newArrayList();
    }

    Map<Long, UserProfileDTO> baseInfoMap = userProfileAppConvertor.toMapUserProfileDTO(
        userProfileGateway
            .mapByUserIds(getFriendUserIds(petRelationshipFriends)));

    Map<Long, Boolean> canStealMap = getCanStealMapMap(cmd,
        getFriendUserIds(petRelationshipFriends));

    return petRelationshipFriends.stream().map(friend -> new PetUserFriendCO()
        .setId(friend.getId())
        .setUserProfile(baseInfoMap.get(friend.getFriendUserId()))
        .setCharge(Objects.equals(canStealMap.get(friend.getFriendUserId()), Boolean.TRUE))
        .setBeanBalance(friend.getBeanBalance())
    ).toList();
  }

  private Map<Long, Boolean> getCanStealMapMap(AppUserIdCmd cmd, Set<Long> friendIds) {
    Map<Long, List<PetUserPetIncomeDetails>> stealableMap = petUserPetIncomeDetailsService
        .mapStealableByUserId(friendIds);

    if (CollectionUtils.isEmpty(stealableMap)) {
      return Maps.newHashMap();
    }

    Map<Long, Boolean> petIncomeMap = petIncomeReceiveService
        .mapNotStealableByIncomeDetailsIds(cmd.getUserId(),
            getPetUserPetIncomeDetailsIds(stealableMap));

    return stealableMap.entrySet().stream().map(entry -> entry.getValue().stream()
            .filter(detail -> !Objects.equals(petIncomeMap.get(detail.getId()), Boolean.TRUE))
            .findFirst()
            .map(detail -> ImmutablePair.of(entry.getKey(), Boolean.TRUE))
            .orElseGet(() -> ImmutablePair.of(entry.getKey(), Boolean.FALSE)))
        .collect(Collectors.toMap(ImmutablePair::getLeft, ImmutablePair::getRight));
  }

  private Set<Long> getPetUserPetIncomeDetailsIds(
      Map<Long, List<PetUserPetIncomeDetails>> stealableMap) {
    return stealableMap.values().stream()
        .flatMap(Collection::stream)
        .map(PetUserPetIncomeDetails::getId)
        .collect(Collectors.toSet());
  }

  private Set<Long> getFriendUserIds(List<PetRelationshipFriendDTO> petRelationshipFriends) {
    return petRelationshipFriends.stream().map(PetRelationshipFriendDTO::getFriendUserId).collect(
        Collectors.toSet());
  }
}
