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

import com.google.common.collect.Lists;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import com.red.circle.other.app.convertor.user.UserConfessionConvertor;
import com.red.circle.other.app.dto.clientobject.user.user.ConfessionRecordCO;
import com.red.circle.other.app.dto.clientobject.user.user.UserConfessionFloatCO;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
import com.red.circle.other.domain.model.user.UserProfile;
import com.red.circle.other.infra.database.rds.entity.user.user.UserConfessionRecord;
import com.red.circle.other.infra.database.rds.service.user.user.ConfessionChanceService;
import com.red.circle.other.infra.database.rds.service.user.user.UserConfessionRecordService;
import com.red.circle.tool.core.collection.CollectionUtils;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

/**
 * 飘动告白内容信息
 *
 * @author zongpubin on 2023/11/14
 */
@Component
@AllArgsConstructor
public class UserConfessionFloatQryExe {

  private final UserRegionGateway regionGateway;
  private final UserProfileGateway userProfileGateway;
  private final UserConfessionConvertor userConfessionConvertor;
  private final ConfessionChanceService confessionChanceService;
  private final UserConfessionRecordService confessionRecordService;

  public UserConfessionFloatCO execute(AppExtCommand cmd) {

    Long confessionNum = confessionChanceService.countConfessionChance(cmd.requiredReqUserId());

    List<UserConfessionRecord> confessionRecords = confessionRecordService.listConfessionRecordFloat(
        regionGateway.getRegionCode(cmd.requiredReqUserId()));

    if (CollectionUtils.isEmpty(confessionRecords)) {
      return new UserConfessionFloatCO()
          .setBottomConfessionRecords(Lists.newArrayList())
          .setTopConfessionRecords(Lists.newArrayList())
          .setConfessionNum(confessionNum);
    }

    Map<Long, UserProfile> userProfileMap = userProfileGateway
        .mapByUserIds(getAllUserIds(confessionRecords));

    List<ConfessionRecordCO> confessionRecordCOList = userConfessionConvertor.toConfessionRecordCO(
        confessionRecords).stream().map(records -> {
      UserProfile userProfile = userProfileMap.get(records.getUserId());
      UserProfile confessionUserProfile = userProfileMap.get(records.getConfessionUserId());
      if (Objects.isNull(userProfile) || Objects.isNull(confessionUserProfile)) {
        return null;
      }
      records.setUserAvatar(userProfile.getUserAvatar());
      records.setUserNickname(userProfile.getUserNickname());
      records.setConfessionUserAvatar(confessionUserProfile.getUserAvatar());
      records.setConfessionUserNickname(confessionUserProfile.getUserNickname());
      return records;
    }).filter(Objects::nonNull).collect(Collectors.toList());

    if (CollectionUtils.isEmpty(confessionRecordCOList)) {
      return new UserConfessionFloatCO()
          .setBottomConfessionRecords(Lists.newArrayList())
          .setTopConfessionRecords(Lists.newArrayList())
          .setConfessionNum(confessionNum);
    }

    if (confessionRecordCOList.size() <= 2) {
      return new UserConfessionFloatCO()
          .setBottomConfessionRecords(Lists.newArrayList())
          .setTopConfessionRecords(confessionRecordCOList)
          .setConfessionNum(confessionNum);
    }
    List<ConfessionRecordCO> topClassRecords = Lists.newArrayList();
    List<ConfessionRecordCO> bottomClassRecords = Lists.newArrayList();
    for (int i = 0; i < confessionRecordCOList.size(); i++) {
      if (i % 2 == 0) {
        bottomClassRecords.add(confessionRecordCOList.get(i));
        continue;
      }
      topClassRecords.add(confessionRecordCOList.get(i));
    }

    return new UserConfessionFloatCO().setConfessionNum(confessionNum)
        .setTopConfessionRecords(topClassRecords)
        .setBottomConfessionRecords(bottomClassRecords);
  }

  private Set<Long> getAllUserIds(List<UserConfessionRecord> results) {
    return results.stream()
        .map(confessionRecord -> Arrays.asList(confessionRecord.getUserId(),
            confessionRecord.getConfessionUserId()))
        .flatMap(Collection::stream)
        .collect(Collectors.toSet());
  }
}
