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

import com.google.common.collect.Lists;
import com.red.circle.common.business.dto.cmd.app.AppIdLongCmd;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.dto.clientobject.team.TeamMemberCO;
import com.red.circle.other.app.dto.clientobject.team.TeamMemberCountResultCO;
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.mongo.dto.team.TeamPolicy;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMember;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMemberTarget;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamPolicyManager;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamProfile;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberTargetService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamPolicyManagerService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamProfileService;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import com.red.circle.tool.core.num.NumUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

/**
 * 团队成员列表.
 *
 * @author pengliang on 2022/12/6
 */
@Component
@RequiredArgsConstructor
public class TeamMemberListQryExe {

  private final TeamMemberService teamMemberService;
  private final UserProfileGateway userProfileGateway;
  private final UserProfileAppConvertor userProfileAppConvertor;
  private final TeamMemberTargetService teamMemberTargetService;
  private final TeamPolicyManagerService teamPolicyManagerService;
  private final TeamProfileService teamProfileService;

  public List<TeamMemberCO> execute(AppIdLongCmd cmd) {

    List<TeamMember> teamMembers = teamMemberService.listTeamMember(cmd.getId(),
        3000);
    if (CollectionUtils.isEmpty(teamMembers)) {
      return Lists.newArrayList();
    }

    Set<Long> memberUserIds = teamMembers.stream().map(TeamMember::getMemberId)
        .collect(Collectors.toSet());
    Map<Long, UserProfileDTO> userProfileMap = userProfileAppConvertor.toMapUserProfileDTO(
        userProfileGateway.mapByUserIds(memberUserIds));

    Map<Long, TeamMemberTarget> teamMemberTargetMap = teamMemberTargetService.mapMemberBillTarget(
        cmd.getId(), memberUserIds, ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt());

    List<TeamMemberCO> teamMemberCOs = teamMembers.stream().map(teamMember -> new TeamMemberCO()
            .setId(teamMember.getMemberId())
            .setUserProfile(userProfileMap.get(teamMember.getMemberId()))
            .setTargetFormat(Optional.ofNullable(teamMemberTargetMap.get(teamMember.getMemberId()))
                    .map(target -> NumUtils.formatLong(target.sumAcceptGiftValue()))
                    .orElse("0"))
            .setTimeHours(Optional.ofNullable(teamMemberTargetMap.get(teamMember.getMemberId()))
                    .map(target -> BigDecimal.valueOf(target.sumAllTargetTime())
                            .divide(BigDecimal.valueOf(60), 2, RoundingMode.DOWN)
                            .stripTrailingZeros().toPlainString())
                    .orElse("0"))
            .setEffectiveDay(Optional.ofNullable(teamMemberTargetMap.get(teamMember.getMemberId()))
                            .map(TeamMemberTarget::sumEffectiveDay)
                            .orElse(0))
            .setUseDiamonds("0")
            .setSurplusDiamonds("0")
            .setRole(Objects.toString(teamMember.getRole()))
            .setWalletWithdrawal(Objects.isNull(teamMember.getWalletWithdrawal()) || Objects.equals(
                    teamMember.getWalletWithdrawal(), Boolean.TRUE))
            .setCreateTime(teamMember.getCreateTime())
    ).collect(Collectors.toList());
    return teamMemberCOs;
  }

  public TeamMemberCountResultCO executeCount(AppIdLongCmd cmd) {
    List<TeamMember> teamMembers = teamMemberService.listTeamMember(cmd.getId(),
            3000);

    if (CollectionUtils.isEmpty(teamMembers)) {
      return new TeamMemberCountResultCO()
              .setMemberQuantity(0)
              .setLevel(null)
              .setTargetFormatSum("0")
              .setTargetSum(0L);
    }

    // 获取团队信息和政策管理器
    TeamProfile teamProfile = teamProfileService.getById(cmd.getId());
    if (teamProfile == null) {
      return new TeamMemberCountResultCO()
              .setMemberQuantity(teamMembers.size())
              .setLevel(null)
              .setTargetFormatSum("0")
              .setTargetSum(0L);
    }

    TeamPolicyManager teamPolicyManager = teamPolicyManagerService.getReleaseByRegionAndType(
            teamProfile.getSysOrigin(), teamProfile.getRegion());
    
    if (teamPolicyManager == null || CollectionUtils.isEmpty(teamPolicyManager.getPolicy())) {
      return new TeamMemberCountResultCO()
              .setMemberQuantity(teamMembers.size())
              .setLevel(null)
              .setTargetFormatSum("0")
              .setTargetSum(0L);
    }

    // 获取团队成员的目标总和
    Set<Long> memberUserIds = teamMembers.stream().map(TeamMember::getMemberId)
            .collect(Collectors.toSet());
    
    Map<Long, TeamMemberTarget> teamMemberTargetMap = teamMemberTargetService.mapMemberBillTarget(
            cmd.getId(), memberUserIds, ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt());
    
    // 计算目标总和
    Long targetSum = teamMemberTargetMap.values().stream()
            .filter(Objects::nonNull)
            .mapToLong(target -> Optional.ofNullable(target.sumAcceptGiftValue()).orElse(0L))
            .sum();

    // 根据团队目标总和匹配对应的TeamPolicy返回对应的挡位
    Integer matchedLevel = findMatchedLevel(teamPolicyManager.getPolicy(), targetSum);

    return new TeamMemberCountResultCO()
            .setMemberQuantity(teamMembers.size())
            .setLevel(matchedLevel)
            .setTargetFormatSum(NumUtils.formatLong(targetSum))
            .setTargetSum(targetSum);
  }

  /**
   * 根据目标总和查找匹配的等级.
   * 逻辑：从高等级到低等级遍历，找到第一个满足条件的等级
   *
   * @param policies 政策列表
   * @param targetSum 目标总和
   * @return 匹配的等级，如果没有匹配则返回null
   */
  private Integer findMatchedLevel(List<TeamPolicy> policies, Long targetSum) {
    if (CollectionUtils.isEmpty(policies) || targetSum == null) {
      return null;
    }

    // 按等级降序排列，从高等级到低等级匹配
    return policies.stream()
            .sorted((p1, p2) -> Integer.compare(p2.getLevel(), p1.getLevel()))
            .filter(policy -> targetSum >= Optional.ofNullable(policy.getTarget()).orElse(0L))
            .findFirst()
            .map(TeamPolicy::getLevel)
            .orElse(0);
  }

    public List<TeamMemberCO> searchTeamMember(Long reqUserId, String account) {
        TeamMember reqTeamMember = teamMemberService.getByMemberId(reqUserId);
        if (reqTeamMember == null) {
            return Collections.emptyList();
        }

        List<UserProfile> userProfiles = userProfileGateway.getByAccount(account);
        if (CollectionUtils.isEmpty(userProfiles)) {
            return Collections.emptyList();
        }
        UserProfile userProfile = userProfiles.get(0);
        TeamMember teamMember = teamMemberService.getByMemberId(userProfile.getId());
        if (teamMember == null || !teamMember.getTeamId().equals(reqTeamMember.getTeamId())) {
            return Collections.emptyList();
        }
        return Collections.singletonList(new TeamMemberCO().setUserProfile(userProfileAppConvertor.toUserProfileDTO(userProfile)));
    }


}
