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

import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMember;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamProfile;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamExchangeSurplusTargetService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamProfileService;
import com.red.circle.other.app.inner.convertor.team.AgencyTeamInnerConvertor;
import com.red.circle.other.app.inner.service.team.AgentTeamClientService;
import com.red.circle.other.inner.enums.team.TeamMemberRole;
import com.red.circle.other.inner.model.dto.agency.agency.TeamExchangeSurplusTargetDTO;
import com.red.circle.other.inner.model.dto.agency.agency.TeamMemberDTO;
import com.red.circle.other.inner.model.dto.agency.agency.TeamProfileDTO;
import com.red.circle.other.inner.model.dto.agency.agency.TeamStatus;
import com.red.circle.other.inner.model.dto.agency.agency.UserTeamRegionDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
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.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

/**
 * 代理团队服务.
 *
 * @author pengliang on 2023/6/1
 */
@Service
@RequiredArgsConstructor
public class AgentTeamClientServiceImpl implements AgentTeamClientService {

  private final TeamMemberService teamMemberService;
  private final TeamProfileService teamProfileService;
  private final AgencyTeamInnerConvertor agencyTeamInnerConvertor;
  private final TeamExchangeSurplusTargetService exchangeSurplusTargetService;

  @Override
  public boolean existsTeamMember(Long userId) {
    return Objects.nonNull(getAvailableProfile(teamMemberService.getByMemberId(userId)));
  }

  @Override
  public boolean existsTeamOwn(Long userId) {
    TeamMember teamMember = teamMemberService.getByMemberId(userId);
    return Objects.nonNull(getAvailableProfile(teamMember))
        && TeamMemberRole.OWN.eq(teamMember.getRole());
  }

  @Override
  public void refreshActiveTime(Long userId) {
    teamMemberService.updateActiveTimeNow(userId);
  }

  @Override
  public TeamMemberDTO getByMemberId(Long memberId) {
    TeamMember teamMember = teamMemberService.getByMemberId(memberId);
    if (Objects.isNull(getAvailableProfile(teamMember))) {
      return null;
    }
    return agencyTeamInnerConvertor.toTeamMemberDTO(teamMember);
  }

  @Override
  public TeamProfileDTO getProfileByOwnUserId(Long ownUserId) {
    return agencyTeamInnerConvertor.toTeamProfileDTO(
        teamProfileService.getAvailableByOwnUserId(ownUserId));
  }

  @Override
  public TeamProfileDTO getProfileByMemberId(Long memberId) {
    TeamMember teamMember = teamMemberService.getByMemberId(memberId);
    TeamProfile teamProfile = getAvailableProfile(teamMember);
    if (Objects.isNull(teamProfile)) {
      return null;
    }
    return agencyTeamInnerConvertor.toTeamProfileDTO(teamProfile);

  }

  @Override
  public List<UserTeamRegionDTO> listUserTeamRegion(Set<Long> userIds) {
    List<TeamMember> teamMembers = teamMemberService.listByMemberIds(userIds);

    if (CollectionUtils.isEmpty(teamMembers)) {
      return CollectionUtils.newArrayList();
    }

    Map<Long, TeamProfile> teamProfilesMap = teamProfileService.listStatusAvailable(
            teamMembers.stream().map(TeamMember::getTeamId).collect(Collectors.toSet()))
        .stream()
        .collect(Collectors.toMap(TeamProfile::getId, v -> v));

    if (CollectionUtils.isEmpty(teamProfilesMap)) {
      return CollectionUtils.newArrayList();
    }

    return teamMembers.stream()
        .filter(member -> teamProfilesMap.containsKey(member.getTeamId()))
        .map(member -> new UserTeamRegionDTO()
        .setUserId(member.getMemberId())
        .setSysOrigin(member.getSysOrigin())
        .setTeamId(member.getTeamId())
        .setRegionId(teamProfilesMap.get(member.getTeamId()).getRegion())
    ).toList();
  }

  @Override
  public Map<Long, TeamProfileDTO> mapProfileByIds(Set<Long> ids) {
    return agencyTeamInnerConvertor.toMapTeamProfileDTO(teamProfileService.mapProfileByIds(ids));
  }

  @Override
  public Map<Long, TeamMemberDTO> mapByMemberIds(Collection<Long> memberIds) {
    return agencyTeamInnerConvertor.toMapTeamMemberDTO(teamMemberService.mapByMemberIds(memberIds));
  }

  @Override
  public List<Long> listMemberIds(Set<Long> userIds) {
    List<TeamMember> teamMembers = teamMemberService.listByMemberIds(userIds);
    if (CollectionUtils.isEmpty(teamMembers)) {
      return CollectionUtils.newArrayList();
    }

    Set<Long> availableTeamIds = teamProfileService.listStatusAvailable(
            teamMembers.stream().map(TeamMember::getTeamId).collect(Collectors.toSet()))
        .stream()
        .map(TeamProfile::getId)
        .collect(Collectors.toSet());
    if (CollectionUtils.isEmpty(availableTeamIds)) {
      return CollectionUtils.newArrayList();
    }

    return teamMembers.stream()
        .filter(member -> availableTeamIds.contains(member.getTeamId()))
        .map(TeamMember::getMemberId)
        .toList();
  }

  @Override
  public TeamProfileDTO getProfileById(Long id) {
    return agencyTeamInnerConvertor.toTeamProfileDTO(teamProfileService.getById(id));
  }


  @Override
  public List<TeamExchangeSurplusTargetDTO> listByCondition(Long lastId, Long userId,
      String sysOrigin,
      Integer dateNumber) {
    return agencyTeamInnerConvertor.toListTeamExchangeSurplusTargetDTO(
        exchangeSurplusTargetService.listByCondition(lastId, userId, sysOrigin, dateNumber));
  }


  @Override
  public String getTotalAmountUsd(Long userId, String sysOrigin, Integer dateNumber) {

    return exchangeSurplusTargetService.getTotalAmountUsd(userId, sysOrigin, dateNumber);
  }

  private TeamProfile getAvailableProfile(TeamMember teamMember) {
    if (Objects.isNull(teamMember)) {
      return null;
    }

    TeamProfile teamProfile = teamProfileService.getById(teamMember.getTeamId());
    if (Objects.isNull(teamProfile) || !TeamStatus.AVAILABLE.equals(teamProfile.getStatus())) {
      return null;
    }
    return teamProfile;
  }

}
