package com.red.circle.other.app.inner.service.user.user.impl;

import com.red.circle.other.app.inner.convertor.user.UserProfileInnerConvertor;
import com.red.circle.other.app.inner.service.user.user.UserOnlineClientService;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.domain.model.user.UserProfile;
import com.red.circle.other.infra.common.user.OnlineStatusCommon;
import com.red.circle.other.infra.database.mongo.entity.user.status.OnlineUser;
import com.red.circle.other.infra.database.mongo.service.user.status.OnlineUserService;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.parse.DataTypeUtils;
import com.red.circle.other.inner.model.cmd.user.OnlineCountQryCmd;
import com.red.circle.other.inner.model.cmd.user.OnlineStatusUploadCmd;
import com.red.circle.other.inner.model.cmd.user.OnlineUserBackQryCmd;
import com.red.circle.other.inner.model.dto.user.OnlineUserDTO;
import com.red.circle.other.inner.model.dto.user.PageOnlineUserDTO;
import com.red.circle.other.inner.enums.user.UserOnlineStatusEnum;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

/**
 * 在线服务.
 *
 * @author pengliang on 2023/6/2
 */
@Service
@RequiredArgsConstructor
public class UserOnlineClientServiceImpl implements UserOnlineClientService {

  private final OnlineUserService onlineUserService;
  private final OnlineStatusCommon onlineStatusCommon;
  private final UserProfileGateway userProfileGateway;
  private final UserProfileInnerConvertor userProfileInnerConvertor;

  @Override
  public void upload(OnlineStatusUploadCmd cmd) {
    onlineStatusCommon.upload(cmd);
  }

  @Override
  public Integer getWeights(Long userId) {
    return onlineStatusCommon.getWeights(userId);
  }

  @Override
  public Long countSessionId(Long sessionId) {
    return onlineUserService.countSessionId(sessionId);
  }

  @Override
  public String getSessionId(Long userId) {
    return onlineUserService.getSessionId(userId);
  }

  @Override
  public void removeByUserId(Long userId) {
    onlineUserService.removeByUserId(userId);
  }

  @Override
  public List<OnlineUserDTO> flowSessionOnlineUser(String sessionId, UserOnlineStatusEnum status,
      Long lastTimingId) {

    List<OnlineUser> onlineUsers = onlineUserService.flowSessionOnlineUser(sessionId, status,
        lastTimingId);

    return toOnlineUserDTOS(onlineUsers);
  }


  @Override
  public Long onlineTotal(OnlineCountQryCmd query) {
    return onlineUserService.count(query);
  }

  @Override
  public List<PageOnlineUserDTO> listBackOnline(OnlineUserBackQryCmd query) {
    return userProfileInnerConvertor.toListPageOnlineUserDTO(
        onlineUserService.getBackOnline(query));
  }

  @Override
  public List<OnlineUserDTO> flowLanguageHallTop200(Long roomId, Long lastTimingId) {
    return toOnlineUserDTOS(onlineUserService.flowLanguageHallTop200(roomId, lastTimingId));
  }

  @Override
  public void updateStatusAndSessionId(Long userId, UserOnlineStatusEnum onlineStatus, Long sessionId) {
    onlineUserService.updateStatusAndSessionId(userId,onlineStatus,sessionId);
  }


  private List<OnlineUserDTO> toOnlineUserDTOS(List<OnlineUser> onlineUsers) {
    if (CollectionUtils.isEmpty(onlineUsers)) {
      return CollectionUtils.newArrayList();
    }

    Map<Long, UserProfile> userProfileMap = userProfileGateway.mapByUserIds(
        onlineUsers.stream().map(OnlineUser::getId).collect(
            Collectors.toSet()));

    return onlineUsers.stream().map(onlineUser -> new OnlineUserDTO()
        .setId(onlineUser.getTimingId())
        .setUserProfile(
            userProfileInnerConvertor.toUserProfileDTO(userProfileMap.get(onlineUser.getId())))
        .setSvipLevel(onlineUser.getSvipLevel())
        .setStatus(onlineUser.getStatus())
        .setWeights(onlineUser.getWeights())
        .setSessionId(DataTypeUtils.toLong(onlineUser.getSessionId()))
    ).filter(onlineUser -> Objects.nonNull(onlineUser.getUserProfile())).toList();
  }


}
