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.other.app.dto.clientobject.dynamic.DynamicCommentListCO;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicCommentLimitCmd;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.domain.model.user.UserProfile;
import com.red.circle.other.infra.database.cache.service.other.DynamicCacheService;
import com.red.circle.other.infra.database.rds.entity.dynamic.DynamicComment;
import com.red.circle.other.infra.database.rds.entity.dynamic.DynamicContent;
import com.red.circle.other.infra.database.rds.service.dynamic.DynamicCommentLikeService;
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.inner.asserts.DynamicErrorCode;
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 org.springframework.stereotype.Component;

/**
 * <p>
 * 动态评价列表.
 * </p>
 *
 * @author pengshigang
 * @since 2022-04-13
 */
@Component
@RequiredArgsConstructor
public class DynamicCommentQryExe {

  private final UserProfileGateway userProfileGateway;
  private final DynamicCacheService dynamicCacheService;
  private final DynamicContentService dynamicContentService;
  private final DynamicCommentService dynamicCommentService;
  private final DynamicCommentLikeService dynamicCommentLikeService;

  public List<DynamicCommentListCO> execute(DynamicCommentLimitCmd cmd) {

    DynamicContent dynamicContent = dynamicContentService.getById(cmd.getDynamicId());
    ResponseAssert.notNull(DynamicErrorCode.CONTENT_IS_NULL, dynamicContent);
    ResponseAssert.isFalse(DynamicErrorCode.CONTENT_DELETE, dynamicContent.getDel());

    List<DynamicComment> comments = pageData(cmd);
    if (CollectionUtils.isEmpty(comments)) {
      return Lists.newArrayList();
    }
    Map<Long, UserProfile> userMap =
        userProfileGateway.mapByUserIds(getUserIds(comments));

    Map<Long, Boolean> commentLikeMap = getCommentLikeMap(cmd, comments);

    return comments.stream().map(comment -> {

      DynamicCommentListCO listCO = new DynamicCommentListCO();
      UserProfile createUser = userMap.get(comment.getCreateUser());
      if (Objects.isNull(createUser)) {
        return null;
      }
      listCO.setUserAvatar(createUser.getUserAvatar());
      listCO.setUserNickname(createUser.getUserNickname());
      listCO.setUserSex(createUser.getUserSex());
      listCO.setUserId(createUser.getId());
      listCO.setRootCommentId(comment.getRootCommentId());

      UserProfile toUser = userMap.get(comment.getToUserId());
      if (Objects.nonNull(toUser)) {
        listCO.setToUserId(toUser.getId());
        listCO.setToUserNickname(toUser.getUserNickname());
      }

      if (Objects.isNull(comment.getRootCommentId()) && Objects.isNull(comment.getToUserId())) {
        listCO.setRootCommentId(comment.getId());
      }

      listCO.setLike(getLike(commentLikeMap, comment));

      listCO.setLikeStrQuantity(getLikeStrQuantity(cmd, comment));
      listCO.setId(comment.getId());
      listCO.setDynamicId(comment.getDynamicContentId());
      listCO.setContent(comment.getContent());
      listCO.setCreateTime(comment.getCreateTime());

      return listCO;

    }).filter(Objects::nonNull).collect(Collectors.toList());
  }

  private Boolean getLike(Map<Long, Boolean> commentLikeMap, DynamicComment comment) {
    return Optional.ofNullable(commentLikeMap.get(comment.getId())).orElse(Boolean.FALSE);
  }

  private Map<Long, Boolean> getCommentLikeMap(DynamicCommentLimitCmd cmd,
      List<DynamicComment> comments) {
    return dynamicCommentLikeService
        .mapByCommentIdsByUserId(comments.stream().map(DynamicComment::getId).collect(
            Collectors.toSet()), cmd.getReqUserId());
  }

  private String getLikeStrQuantity(DynamicCommentLimitCmd cmd, DynamicComment comment) {

    return NumUtils.formatLong(Optional.ofNullable(
            dynamicCacheService.getCommentLikeQuantity(cmd.getDynamicId(), comment.getId()))
        .orElse(0L));
  }

  private Set<Long> getUserIds(List<DynamicComment> comments) {

    Set<Long> userIds = comments.stream().map(DynamicComment::getCreateUser)
        .filter(Objects::nonNull).collect(Collectors.toSet());

    userIds.addAll(comments.stream().map(DynamicComment::getToUserId).filter(Objects::nonNull)
        .collect(Collectors.toSet()));

    return userIds;
  }

  private List<DynamicComment> pageData(DynamicCommentLimitCmd cmd) {
    return dynamicCommentService.pageByTimeDesc(cmd.getPageNumber(), cmd.getDynamicId());
  }

}
