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

import com.google.common.collect.Lists;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.CommonErrorCode;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.dto.clientobject.dynamic.DynamicListCO;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicMyLimitCmd;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.infra.database.rds.entity.dynamic.DynamicContent;
import com.red.circle.other.infra.database.rds.entity.dynamic.DynamicPicture;
import com.red.circle.other.infra.database.rds.entity.dynamic.DynamicTag;
import com.red.circle.other.infra.database.rds.service.dynamic.DynamicCommentService;
import com.red.circle.other.infra.database.rds.service.dynamic.DynamicContentService;
import com.red.circle.other.infra.database.rds.service.dynamic.DynamicLikeService;
import com.red.circle.other.infra.database.rds.service.dynamic.DynamicPictureService;
import com.red.circle.other.infra.database.rds.service.dynamic.DynamicTagService;
import com.red.circle.other.infra.database.rds.service.user.user.UserSubscriptionService;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
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;

/**
 * <p>
 * 我的动态内容列表.
 * </p>
 *
 * @author pengshigang
 * @since 2022-04-12
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class DynamicMyQryExe {

  private final DynamicTagService dynamicTagService;
  private final UserProfileGateway userProfileGateway;
  private final DynamicLikeService dynamicLikeService;
  private final DynamicPictureService dynamicPictureService;
  private final DynamicContentService dynamicContentService;
  private final DynamicCommentService dynamicCommentService;
  private final UserSubscriptionService userSubscriptionService;
  private final UserProfileAppConvertor userProfileAppConvertor;

  public List<DynamicListCO> execute(DynamicMyLimitCmd cmd) {

    List<DynamicContent> dynamics = dynamicContentService
        .pageByTimeDesc(cmd.getPageNumber(), cmd.getUserId());

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

    Set<Long> ids = getIds(dynamics);
    if (CollectionUtils.isEmpty(ids)) {
      return Lists.newArrayList();
    }

    Boolean isMySubscription = isMySubscription(cmd);

    //自己是否已点赞
    Map<Long, Boolean> likeMap = getLikeMap(cmd, ids);

    UserProfileDTO user = userProfileAppConvertor.toUserProfileDTO(
        userProfileGateway.getByUserId(cmd.getUserId())
    );
    ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_RECORD_INFO, user);
    Map<Long, Long> likeQuantityMap = dynamicLikeService.mapLikeQuantity(ids);
    Map<Long, DynamicTag> tagMap = dynamicTagService.mapByIds(getTagIds(dynamics));
    Map<Long, Integer> commentQuantityMap = dynamicCommentService.mapCommentQuantity(ids);
    Map<Long, List<DynamicPicture>> pictureMap = dynamicPictureService.mapPreviewGroup(ids);

    return dynamics.stream().map(dynamic -> {

      DynamicListCO result = new DynamicListCO();
      processUser(user, result);
      processTag(tagMap, dynamic, result);
      processBase(dynamic, result, pictureMap);
      result.setSubscription(isMySubscription);
      result.setLikeStrQuantity(NumUtils.formatLong(likeQuantityMap.get(dynamic.getId())));
      result.setLike(Optional.ofNullable(likeMap.get(dynamic.getId())).orElse(Boolean.FALSE));
      result.setCommentStrQuantity(NumUtils.formatInt(commentQuantityMap.get(dynamic.getId())));

      return result;
    }).collect(Collectors.toList());

  }

  private Boolean isMySubscription(DynamicMyLimitCmd cmd) {

    if (Objects.equals(cmd.getUserId(), cmd.getReqUserId())) {
      return Boolean.TRUE;
    }

    return Objects.nonNull(
        userSubscriptionService.getBySubscription(cmd.getReqUserId(), cmd.getUserId())
    );
  }

  private Map<Long, Boolean> getLikeMap(DynamicMyLimitCmd cmd, Set<Long> ids) {
    return dynamicLikeService.mapByContentIdsByUserId(ids, cmd.getReqUserId());
  }


  private void processBase(DynamicContent dynamic, DynamicListCO result,
      Map<Long, List<DynamicPicture>> pictureMap) {

    DynamicPopularQryExe.processBaseDetails(dynamic, result, pictureMap);
  }

  private void processUser(UserProfileDTO baseInfo, DynamicListCO result) {
    result.setUserId(baseInfo.getId());
    result.setUserAvatar(baseInfo.getUserAvatar());
    result.setUserSex(baseInfo.getUserSex());
    result.setUserNickname(baseInfo.getUserNickname());
  }

  private void processTag(Map<Long, DynamicTag> tagMap, DynamicContent dynamic,
      DynamicListCO result) {

    DynamicTag tag = tagMap.get(dynamic.getTagId());
    if (Objects.nonNull(tag)) {
      result.setTag(tag.getTag());
      result.setTagId(tag.getId());
    }
  }

  private Set<Long> getTagIds(List<DynamicContent> dynamics) {
    return dynamics.stream().map(DynamicContent::getTagId).collect(Collectors.toSet());
  }

  private Set<Long> getIds(List<DynamicContent> dynamics) {
    return dynamics.stream().map(DynamicContent::getId).collect(Collectors.toSet());
  }

}
