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

import com.red.circle.framework.dto.PageResult;
import com.red.circle.other.app.dto.clientobject.dynamic.DynamicCommentListCO;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicChildCommentLimitCmd;
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.service.dynamic.DynamicCommentLikeService;
import com.red.circle.other.infra.database.rds.service.dynamic.DynamicCommentService;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.num.NumUtils;
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;

/**
 * 动态子评论列表查询.
 *
 * @author pengshigang
 * @since 2025-01-29
 */
@Component
@RequiredArgsConstructor
public class DynamicChildCommentQryExe {

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

  public PageResult<DynamicCommentListCO> execute(DynamicChildCommentLimitCmd cmd) {

    PageResult<DynamicComment> comments = pageData(cmd);
    if (CollectionUtils.isEmpty(comments.getRecords())) {
      return PageResult.newPageResult(0);
    }

    Map<Long, UserProfile> userMap = userProfileGateway.mapByUserIds(getUserIds(comments));
    Map<Long, Boolean> commentLikeMap = getCommentLikeMap(cmd, comments);

    return comments.convert(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());
      listCO.setReplyCommentId(comment.getReplyCommentId());

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

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

      return listCO;

    });
  }

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

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

  private String getLikeStrQuantity(DynamicComment comment) {
    return NumUtils.formatLong(Optional.ofNullable(
            dynamicCacheService.getCommentLikeQuantity(comment.getDynamicContentId(), comment.getId()))
        .orElse(0L));
  }

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

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

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

    return userIds;
  }

  private PageResult<DynamicComment> pageData(DynamicChildCommentLimitCmd cmd) {
    return dynamicCommentService.pageChildCommentsByTimeDesc(cmd.getPageReq(),
        cmd.getRootCommentId());
  }

}
