package com.red.circle.other.app.common.room;

import com.google.common.collect.Lists;
import com.red.circle.common.business.enums.DynamicMessageEnum;
import com.red.circle.external.inner.endpoint.message.NewsletterClient;
import com.red.circle.external.inner.model.cmd.message.NewsletterResultCmd;
import com.red.circle.external.inner.model.enums.message.NewsletterEvent;
import com.red.circle.mq.business.model.event.dynamic.DynamicEvent;
import com.red.circle.other.infra.database.rds.entity.dynamic.DynamicMessage;
import com.red.circle.other.infra.database.rds.entity.dynamic.DynamicTimeline;
import com.red.circle.other.infra.database.rds.entity.user.user.UserSubscription;
import com.red.circle.other.infra.database.rds.service.approval.ApprovalDynamicContentService;
import com.red.circle.other.infra.database.rds.service.dynamic.DynamicContentService;
import com.red.circle.other.infra.database.rds.service.dynamic.DynamicMessageService;
import com.red.circle.other.infra.database.rds.service.dynamic.DynamicTimelineService;
import com.red.circle.other.infra.database.rds.service.user.user.UserSubscriptionService;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.TimestampUtils;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 动态.
 *
 * @author pengshigang
 * @since 2022-4-12
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class DynamicCommon {

  private final NewsletterClient newsletterClient;
  private final DynamicContentService dynamicContentService;
  private final DynamicMessageService dynamicMessageService;
  private final DynamicTimelineService dynamicTimelineService;
  private final UserSubscriptionService userSubscriptionService;
  private final ApprovalDynamicContentService approvalDynamicContentService;


  /**
   * 关注用户业务
   *
   * @param userId         操作用户id
   * @param followedUserId 被关注用户id
   */
  public void follow(Long userId, Long followedUserId) {

    //获得被关注用户的发布内容
    List<DynamicTimeline> timelines = dynamicTimelineService.ownListByUserId(followedUserId);
    if (CollectionUtils.isEmpty(timelines)) {
      return;
    }

    //将被关注用户的数据插入到自己的时间轴中
    Lists.partition(timelines, 200).parallelStream()
        .forEach(timelineList -> dynamicTimelineService.saveBatch(
            timelineList.parallelStream().map(obj -> new DynamicTimeline()
                    .setDynamicContentId(obj.getDynamicContentId())
                    .setCreateTime(obj.getCreateTime())
                    .setCreateUser(userId)
                    .setOwn(Boolean.FALSE)
                )
                .collect(Collectors.toList())));

  }

  /**
   * 取消关注用户业务
   *
   * @param userId           操作用户id
   * @param unfollowedUserId 被取消关注用户id
   */
  public void unfollow(Long userId, Long unfollowedUserId) {

    //获得需要取消关注用户的发布内容
    List<DynamicTimeline> timelines = dynamicTimelineService.ownListByUserId(unfollowedUserId);
    if (CollectionUtils.isEmpty(timelines)) {
      return;
    }

    //将被关注用户的数据插入到自己的时间轴中
    Lists.partition(timelines, 100).parallelStream()
        .forEach(timelineList -> {

          //获得需要取关的内容id
          Set<Long> contentIds = timelineList.parallelStream()
              .map(DynamicTimeline::getDynamicContentId)
              .collect(Collectors.toSet());

          if (CollectionUtils.isEmpty(contentIds)) {
            return;
          }

          //将自己时间轴中属于被取关的内容删除
          dynamicTimelineService.delete()
              .in(DynamicTimeline::getDynamicContentId, contentIds)
              .eq(DynamicTimeline::getCreateUser, userId)
              .execute();

        });

  }

  /**
   * 自己发布动态时，给关注自己的用户添加动态
   *
   * @param dynamicEvent 参数
   */
  public void toFollowUserAddDynamic(DynamicEvent dynamicEvent) {

    List<UserSubscription> subscriptions = userSubscriptionService.getAllBySubscriptionUserId(
        dynamicEvent.getUserId());

    if (CollectionUtils.isEmpty(subscriptions)) {
      return;
    }

    Lists.partition(subscriptions, 200).parallelStream()
        .forEach(friendList -> dynamicTimelineService
            .saveBatch(friendList.parallelStream().map(subscription -> new DynamicTimeline()
                .setOwn(Boolean.FALSE)
                .setDynamicContentId(dynamicEvent.getDynamicContentId())
                .setRegion(dynamicEvent.getRegion())
                .setCreateUser(subscription.getUserId())
                .setCreateTime(dynamicEvent.getTimestamp())
            ).toList()));
  }


  /**
   * 删除自己动态内容
   *
   * @param contentId 动态内容id
   */
  public void deleteOwnDynamic(Long contentId) {

    //删除时间轴上的所有contentId关联的动态数据
    dynamicTimelineService.deleteByDynamicContentId(contentId);

  }

  /**
   * 发送消息
   *
   * @param toUserId 接收用户
   */
  public void sendMsg(Long toUserId) {

    if (Objects.isNull(toUserId)) {
      return;
    }

    Integer count = dynamicMessageService.getCountByToUserId(toUserId);

    log.info("该用户 {} 动态评论或点赞消息总数量发送", toUserId);
    newsletterClient.send(new NewsletterResultCmd()
        .setUserIds(List.of(toUserId))
        .setEvent(NewsletterEvent.DYNAMIC_MESSAGE_QUANTITY)
        .setData(count <= 0 ? 1 : count)
    );
  }

  /**
   * 系统删除违规动态与时间轴动态信息
   */
  public void systemDeleteDynamic(Long dynamicId) {

    Long userId = dynamicContentService.getCreateUserById(dynamicId);
    if (Objects.isNull(userId)) {
      return;
    }

    dynamicContentService.deleteById(dynamicId);
    dynamicTimelineService.deleteByDynamicContentId(dynamicId);
    approvalDynamicContentService.deleteByDynamicId(dynamicId);

    DynamicMessage dynamicMessage = new DynamicMessage();
    dynamicMessage.setDynamicContentId(dynamicId);
    dynamicMessage.setToUserId(userId);
    dynamicMessage.setType(DynamicMessageEnum.DYNAMIC_VIOLATION.name());
    dynamicMessage.setCreateTime(TimestampUtils.now());
    dynamicMessageService.save(dynamicMessage);

    sendMsg(userId);

  }


}

