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

import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.red.circle.component.mq.MessageEvent;
import com.red.circle.component.mq.service.FixedTopic;
import com.red.circle.component.mq.service.SenderService;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.mq.business.model.event.team.TeamSalaryCountEvent;
import com.red.circle.mq.rocket.business.streams.TeamSalaryCountSink;
import com.red.circle.other.app.inner.convertor.user.UserProfileInnerConvertor;
import com.red.circle.other.app.inner.service.team.TeamBillCycleClientService;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.infra.convertor.team.TeamInfraConvertor;
import com.red.circle.other.infra.database.mongo.dto.team.TeamBillMemberTarget;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamBillCycle;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamImportanceLog;
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.entity.user.region.SysRegionConfig;
import com.red.circle.other.infra.database.mongo.service.activity.AgentActivityCountService;
import com.red.circle.other.infra.database.mongo.service.team.TeamBillCycleUtils;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamBillCycleService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamImportanceLogService;
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.infra.database.mongo.service.user.region.SysRegionConfigService;
import com.red.circle.other.infra.database.rds.entity.team.BillDiamondBalance;
import com.red.circle.other.infra.database.rds.entity.team.UserHistoryIdentity;
import com.red.circle.other.infra.database.rds.service.team.BillDiamondBalanceService;
import com.red.circle.other.infra.database.rds.service.team.BusinessDevelopmentBaseInfoService;
import com.red.circle.other.infra.database.rds.service.team.BusinessDevelopmentTeamService;
import com.red.circle.other.infra.database.rds.service.team.UserHistoryIdentityService;
import com.red.circle.other.infra.database.rds.service.user.device.LatestMobileDeviceService;
import com.red.circle.other.inner.asserts.team.TeamErrorCode;
import com.red.circle.other.inner.asserts.user.UserErrorCode;
import com.red.circle.other.inner.enums.team.TeamBillCycleStatus;
import com.red.circle.other.inner.enums.team.TeamMemberTargetIndex;
import com.red.circle.other.inner.enums.team.TeamMemberTargetSettlementResult;
import com.red.circle.other.inner.enums.team.TeamMemberTargetStatus;
import com.red.circle.other.inner.model.cmd.team.TeamBillByConditionQryCmd;
import com.red.circle.other.inner.model.cmd.team.TeamBillCycleBackQryCmd;
import com.red.circle.other.inner.model.cmd.team.TeamCalculatorWorkCmd;
import com.red.circle.other.inner.model.cmd.team.TeamMemberTargetResetCmd;
import com.red.circle.other.inner.model.dto.agency.agency.TeamBillAnchorStatisticsModelDTO;
import com.red.circle.other.inner.model.dto.agency.agency.TeamBillCycleDTO;
import com.red.circle.other.inner.model.dto.agency.agency.TeamBillSettleResultDTO;
import com.red.circle.other.inner.model.dto.agency.agency.TeamCalculatorWorkResultDTO;
import com.red.circle.other.inner.model.dto.agency.agency.TeamRemark;
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.DateFormatConstant;
import com.red.circle.tool.core.date.LocalDateTimeUtils;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

/**
 * 团队账单.
 *
 * @author pengliang on 2023/10/17
 */
@Service
@RequiredArgsConstructor
public class TeamBillCycleClientServiceImpl implements TeamBillCycleClientService {

  private static final Logger log = LoggerFactory.getLogger(TeamBillCycleClientServiceImpl.class);
  private final SenderService senderService;
  private final TeamMemberService teamMemberService;
  private final UserProfileGateway userProfileGateway;
  private final TeamInfraConvertor teamInfraConvertor;
  private final TeamProfileService teamProfileService;
  private final TeamBillCycleService teamBillCycleService;
  private final SysRegionConfigService sysRegionConfigService;
  private final TeamMemberTargetService teamMemberTargetService;
  private final TeamImportanceLogService teamImportanceLogService;
  private final TeamPolicyManagerService teamPolicyManagerService;
  private final AgentActivityCountService agentActivityCountService;
  private final LatestMobileDeviceService latestMobileDeviceService;
  private final UserProfileInnerConvertor userProfileInnerConvertor;
  private final UserHistoryIdentityService userHistoryIdentityService;
  private final BusinessDevelopmentBaseInfoService developmentBaseInfoService;
  private final BusinessDevelopmentTeamService businessDevelopmentTeamService;

  private final BillDiamondBalanceService billDiamondBalanceService;

  @Override
  public Long getLatestBillIdByTeamId(Long teamId) {
    return teamBillCycleService.getLatestBillIdByTeamId(teamId);
  }

  @Override
  public List<TeamBillCycleDTO> listBillTable(TeamBillCycleBackQryCmd query) {

    if (StringUtils.isBlank(query.getSysOrigin())) {
      return Lists.newArrayList();
    }

    if (Objects.nonNull(query.getOwnUserId())) {

      TeamProfile teamProfile = getTeamProfile(query);

      if (Objects.isNull(teamProfile)) {
        return Lists.newArrayList();
      }

      if (Objects.nonNull(query.getTeamId())
          && !Objects.equals(teamProfile.getId(), query.getTeamId())) {
        return Lists.newArrayList();
      }

      query.setTeamId(teamProfile.getId());
    }

    return assembleTeamBillCycleVO(query);
  }

  @Override
  public TeamCalculatorWorkResultDTO calculatorWork(TeamCalculatorWorkCmd param) {
    TeamBillCycle teamBillCycle = teamBillCycleService.getByBillId(param.getBillId());
    ResponseAssert.notNull(TeamErrorCode.BILL_DOES_NOT_EXIST, teamBillCycle);

    TeamPolicyManager teamPolicyManager = Objects.nonNull(param.getPolicyId())
        ? teamPolicyManagerService.getById(param.getPolicyId())
        : teamPolicyManagerService.getReleaseByRegionAndType(
            teamBillCycle.getSysOrigin(),
            teamBillCycle.getRegion());
    ResponseAssert.notNull(TeamErrorCode.NOT_FOUND_RELEASE_POLICY, teamPolicyManager);

    List<TeamMemberTarget> teamMemberTargets = getTeamMemberTargets(teamBillCycle);

    List<TeamBillMemberTarget> teamBillMemberTargets = TeamBillCycleUtils.calculatorPolicyTarget(
        teamMemberTargets, teamPolicyManager);

    return new TeamCalculatorWorkResultDTO()
        .setWorkMembers(
            CollectionUtils.isNotEmpty(teamMemberTargets) ? teamMemberTargets.size() : 0)
        .setFinishMembers(teamBillMemberTargets.size())
        .setMemberSalary(sumMemberSalary(teamBillMemberTargets))
        .setOwnSalary(ownSalary(teamBillMemberTargets))
        .setTotalSalary(ownTotalSalary(teamBillMemberTargets))
        .setPolicyId(teamPolicyManager.getId());
  }

  @Override
  public void addInternalRemarks(Long id, TeamRemark remark) {
    teamBillCycleService.addInternalRemarks(id, remark);
  }

  @Override
  public void removeInternalRemarks(Long id, String remarkId) {
    teamBillCycleService.removeInternalRemarks(id, remarkId);
  }

  @Override
  public void updateRemarks(Long id, String remarks) {
    teamBillCycleService.updateRemarks(id, remarks);
  }


  @Override
  public void updateStatus(Long billId, TeamBillCycleStatus status, Long updateUser) {
    teamBillCycleService.updateStatus(billId, status, updateUser);
  }

  @Override
  public List<TeamBillAnchorStatisticsModelDTO> queryTeamBillByCondition(
      TeamBillByConditionQryCmd cmd) {
    // 查询团队账单
    List<TeamBillCycleDTO> billCycleList = teamInfraConvertor.toListTeamBillCycleDTO(
        teamBillCycleService.queryTeamBillByCondition(cmd.getSysOrigin(), cmd.getBillStatus(),
            cmd.getRegion(), cmd.getMonthDate()));

    List<TeamBillAnchorStatisticsModelDTO> result = Lists.newArrayList();
    // 获得区域名称
    String regionName = sysRegionConfigService.getRegionName(cmd.getRegion());

    // 获取团队区域政策
    Map<String, TeamPolicyManager> mapRegionPolicy = mapRegionPolicyManager(cmd);

    // 团队信息
    Map<Long, TeamProfile> teamProfileMap =
        teamProfileService.mapProfileByIds(
            getTeamIds(billCycleList));

    // 团队归属bd userId
    Map<Long, Long> bdTeamUserMap =
        businessDevelopmentTeamService.mapTeamBdUserId(
            billCycleList.stream().map(TeamBillCycleDTO::getTeamId).collect(Collectors.toSet())
        );

    // 获取bd归属leader
    Map<Long, Long> bdLeaderUserMap =
        developmentBaseInfoService.mapBdLeaderUserId(
            new HashSet<>(bdTeamUserMap.values()));
    billCycleList.forEach(billCycle -> {
      // 团队目标列表
      List<TeamMemberTarget> targets = getTeamMemberTargets(billCycle);

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

      // 团队资料
      TeamProfile teamProfile = teamProfileMap.get(billCycle.getTeamId());
      if (Objects.isNull(teamProfile)) {
        return;
      }

      // 团队成员id
      Set<Long> userIds = getMemberUserIds(targets);
      if (CollectionUtils.isEmpty(userIds)) {
        return;
      }
      // 设备列表
      Map<Long, String> mapImei = latestMobileDeviceService.mapImeiByIds(userIds);
      // 成员列表
      Map<Long, UserProfileDTO> mapUserProfile = userProfileInnerConvertor.toMapUserProfileDTO(
          userProfileGateway.mapByUserIds(userIds));
      Map<Long, TeamMember> teamMemberMap = teamMemberService.mapByMemberIds(userIds);
      // 创建人信息
      UserProfileDTO ownUser = getTeamOwnUser(teamProfile.getOwnUserId());
      // BD用户
      UserProfileDTO bdUser = getBdUserProfile(billCycle);
      // 历史身份
      Map<Long, UserHistoryIdentity> userHistoryIdentityMap = userHistoryIdentityService.mapByIds(
          userIds);

      List<TeamBillAnchorStatisticsModelDTO> models = targets.stream().map(target -> {

        UserProfileDTO userProfile = mapUserProfile.get(target.getUserId());
        if (Objects.isNull(userProfile)) {
          return null;
        }
        Long bdUserId = bdTeamUserMap.get(billCycle.getTeamId());
        TeamBillAnchorStatisticsModelDTO model = new TeamBillAnchorStatisticsModelDTO()
            .setBillId(billCycle.getId().toString())
            .setDateNumber(billCycle.getBillBelong())
            .setRegion(regionName)
            .setUserNickname(userProfile.getUserNickname())
            .setAnchorAccount(userProfile.actualAccount())
            .setAnchorId(Objects.toString(userProfile.getId()))
            .setAgentAccount(Objects.isNull(ownUser) ? "" : ownUser.actualAccount())
            .setAgentId(Objects.isNull(ownUser) ? "" : Objects.toString(ownUser.getId()))
            .setAgentCreateUserId(Objects.toString(teamProfile.getCreateUser(), ""))
            .setDevice(mapImei.get(target.getUserId()))
            .setAccountStatusName(userProfile.getAccountStatusName())
            .setBdAccount(Objects.isNull(bdUser) ? "" : bdUser.actualAccount())
            .setBillStatus(getBillStatusName(billCycle.getStatus()))
            .setAgentCreateTime(
                LocalDateTimeUtils.format(LocalDateTimeUtils.convert(teamProfile.getCreateTime()),
                    DateFormatConstant.yyyy_MM_dd_HH_mm_ss))
            .setAnchorJointTime(Optional.ofNullable(teamMemberMap.get(userProfile.getId()))
                .map(teamMember ->
                    LocalDateTimeUtils.format(
                        LocalDateTimeUtils.convert(teamMember.getCreateTime()),
                        DateFormatConstant.yyyy_MM_dd_HH_mm_ss))
                .orElse(""))
            .setHistoryIdentity(
                Optional.ofNullable(userHistoryIdentityMap.get(userProfile.getId()))
                    .map(
                        identity -> StringUtils.join(
                            userHistoryIdentityService.getLabels(identity),
                            ",")).orElse("-")
            )
            .setBdUserId(Objects.toString(bdUserId, "-"))
            .setBdLeaderId(Objects.toString(bdLeaderUserMap.get(bdUserId), "-"));

        if (TeamBillCycleStatus.HANG_UP.equals(billCycle.getStatus())) {
          return model;
        }

        TeamMemberTargetSettlementResult settlementResult = target.getSettlementResult();
        if (TeamBillCycleStatus.SETTLED.equals(billCycle.getStatus()) && Objects.nonNull(
            settlementResult)) {
          model.setOnlineTime(settlementResult.getOnlineTime());
          model.setRoomValue(settlementResult.getRoomValue());
          model.setGiftValue(settlementResult.getAcceptGiftValue());
          model.setLevel(settlementResult.getLevel());
          model.setHostSalary(settlementResult.getMemberSalary());
          model.setAgentSalary(settlementResult.getOwnSalary());
          model.setTotalSalary(settlementResult.getTotalSalary());
          return model;
        }

        TeamPolicyManager teamPolicyManager = Objects.isNull(billCycle.getSettleResult())
            ? mapRegionPolicy.get(billCycle.getRegion())
            : teamInfraConvertor.toTeamPolicyManager(billCycle.getSettleResult().getPolicy());

        if (Objects.isNull(teamPolicyManager)) {
          return model;
        }

        TeamBillMemberTarget memberTarget = TeamBillCycleUtils.calculatorPolicyTarget(target,
            teamPolicyManager);
        model.setOnlineTime(memberTarget.getOnlineTime());
        model.setRoomValue(memberTarget.getRoomValue());
        model.setGiftValue(memberTarget.getAcceptGiftValue());
        model.setLevel(memberTarget.getLevel());
        model.setHostSalary(memberTarget.getMemberSalary());
        model.setAgentSalary(memberTarget.getOwnSalary());
        model.setTotalSalary(memberTarget.getTotalSalary());
        return model;
      }).filter(Objects::nonNull).collect(Collectors.toList());
      if (CollectionUtils.isNotEmpty(models)) {
        result.addAll(models);
      }
    });
    return result;
  }

  @Override
  public void resetUnpaidBillMemberTarget(TeamMemberTargetResetCmd param) {

    TeamMember teamMember = teamMemberService.getByMemberId(param.getResetUserId());
    ResponseAssert.notNull(TeamErrorCode.USER_NOT_TEAM_MEMBER, teamMember);

    TeamProfile teamProfile =
        teamProfileService.getById(teamMember.getTeamId());
    ResponseAssert.notNull(TeamErrorCode.TEAM_NOT_FOUND, teamProfile);

    Boolean isOpenAutoSalary = isOpenDailyAutoSalary(teamProfile.getRegion());

    Integer billBelong = ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt();
    TeamMemberTarget target = teamMemberTargetService.getUserByBillId(teamMember.getMemberId(),
        billBelong);

    teamImportanceLogService.add(new TeamImportanceLog()
        .setRemarks("[后台]点击了重置目标[Target:" + param.getTarget() + "]")
        .setSysOrigin(teamMember.getSysOrigin())
        .setAssociateId(teamMember.getTeamId())
        .setBeProcessUserId(teamMember.getMemberId())
        .setCreateUser(param.getUpdateUser())
        .setCreateUserOrigin(1)
    );

    if (Objects.isNull(target)) {

      // 代理活动 - 由于没有成员目标账单所以增加目标
      agentActivityCountService.incrTarget(teamMember.getTeamId(), param.getTarget().longValue(),
          teamProfile.getRegion());

      teamMemberTargetService.createIfAbsent(new TeamMemberTarget()
          .setTimeId(IdWorkerUtils.getId())
          .setSysOrigin(teamMember.getSysOrigin())
          .setTeamId(teamMember.getTeamId())
          .setBillBelong(ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt())
          .setBillTitle(ZonedDateTimeAsiaRiyadhUtils.nowFormat(DateFormatConstant.MM_SLASH_YYYY))
          .setStatus(Boolean.TRUE.equals(isOpenAutoSalary) ? TeamMemberTargetStatus.AUTO
              : TeamMemberTargetStatus.NOT_RECORDED)
          .setUserId(teamMember.getMemberId())
          .setDailyTargets(List.of(new TeamMemberTargetIndex()
              .setOwnOnlineTime(0L)
              .setOtherOnlineTime(0L)
              .setAcceptGiftValue(param.getTarget().longValue())
              .setGiveGiftValue(0L)
              .setRoomValue(0L)
              .setDateNumber(ZonedDateTimeAsiaRiyadhUtils.nowDateToInt())
              .setCreateTime(TimestampUtils.now())
              .setUpdateTime(TimestampUtils.now())
          ))
          .setCreateTime(TimestampUtils.now())
          .setUpdateTime(TimestampUtils.now())
      );

      // 重新统计团队未出帐账单数据消息
      sendTeamSalaryCountMq(Set.of(teamMember.getTeamId()));
      return;
    }

    // 代理活动
    agentActivityCount(param, teamMember, teamProfile, target);

    teamMemberTargetService.updateTargetCover(
        target.getUserId(),
        billBelong,
        new TeamMemberTargetIndex()
            .setOwnOnlineTime(target.sumOwnOnlineTime())
            .setOtherOnlineTime(target.sumOtherOnlineTime())
            .setAcceptGiftValue(param.getTarget().longValue())
            .setGiveGiftValue(target.sumGiveGiftValue())
            .setRoomValue(target.sumRoomValue())
            .setDateNumber(ZonedDateTimeAsiaRiyadhUtils.nowDateToInt())
            .setCreateTime(TimestampUtils.now())
            .setUpdateTime(TimestampUtils.now())
    );

    // 重新统计团队未出帐账单数据消息
    sendTeamSalaryCountMq(Set.of(teamMember.getTeamId()));
  }

  @Override
  public TeamBillCycleDTO getBillByTeamId(Long teamId) {
    TeamBillCycle teamBillCycle = teamBillCycleService.getTeamUnpaidBill(teamId);

    if (Objects.isNull(teamBillCycle)) {
      return new TeamBillCycleDTO();
    }

    TeamProfile teamProfile = teamProfileService.getById(teamBillCycle.getTeamId());

    TeamBillCycleDTO vo = teamInfraConvertor.toTeamBillCycleDTO(teamBillCycle);

    if (Objects.nonNull(teamProfile)) {
      TeamPolicyManager policyManager = teamPolicyManagerService.getReleaseByRegionAndType(
          teamProfile.getSysOrigin(),
          teamProfile.getRegion());

      vo.setTeamProfile(teamInfraConvertor.toTeamProfileDTO(teamProfile));

      if (Objects.isNull(vo.getSettleResult()) || Objects.isNull(policyManager)) {

        List<TeamMemberTarget> teamMemberTargets = getTeamMemberTargets(teamBillCycle);

        List<TeamBillMemberTarget> teamBillMemberTargets = TeamBillCycleUtils
            .calculatorPolicyDiamondTarget(teamMemberTargets, policyManager);

        // 结算账单.
        vo.setSettleResult(new TeamBillSettleResultDTO()
            .setPolicy(teamInfraConvertor.toTeamPolicyManagerDTO(policyManager))
            .setWorkMembers(countWorkMembers(teamMemberTargets))
            .setFinishMembers(teamBillMemberTargets.size())
            .setMemberSalary(sumMemberSalary(teamBillMemberTargets))
            .setOwnSalary(ownSalary(teamBillMemberTargets))
            .setTotalSalary(ownTotalSalary(teamBillMemberTargets))
        );
      }
    }

    return vo;
  }


  private void agentActivityCount(TeamMemberTargetResetCmd param, TeamMember teamMember,
      TeamProfile teamProfile, TeamMemberTarget target) {

    long tmpTarget = target.sumAcceptGiftValue() - param.getTarget().longValue();
    if (tmpTarget >= 0) {
      agentActivityCountService.reduceTarget(Set.of(teamMember.getTeamId()), tmpTarget);
    } else {
      agentActivityCountService.incrTarget(teamMember.getTeamId(),
          param.getTarget().longValue() - target.sumAcceptGiftValue(),
          teamProfile.getRegion());
    }
  }

  /**
   * 重新统计团队未出帐账单数据消息.
   */
  private void sendTeamSalaryCountMq(Set<Long> teamIds) {

    senderService.sendEventMessage(MessageEvent.builder()
        .consumeId(IdWorkerUtils.getIdStr())
        .topic(FixedTopic.RC_DEFAULT_APP_ORDINARY)
        .tag(TeamSalaryCountSink.TAG)
        .body(new TeamSalaryCountEvent()
            .setTeamIds(teamIds)
            .setTimestamp(TimestampUtils.now())
        )
        .build());

  }

  private Boolean isOpenDailyAutoSalary(String regionId) {

    SysRegionConfig region = sysRegionConfigService.getById(regionId);
    ResponseAssert.notNull(UserErrorCode.SYS_REGION_NOT_EXIST_ERROR, region);

    if (CollectionUtils.isEmpty(region.getMetadata())) {
      return Boolean.FALSE;
    }

    return Objects.equals(region.getMetadata().get("openDailyAutoSalary"), "true");
  }


  private String getBillStatusName(TeamBillCycleStatus status) {

    if (Objects.equals(status, TeamBillCycleStatus.UNPAID)) {
      return "未出账: 当前进行中的";
    }
    if (Objects.equals(status, TeamBillCycleStatus.PAY_OUT)) {
      return "已出账: 本期账单已结束， 等待结算";
    }
    if (Objects.equals(status, TeamBillCycleStatus.SETTLED)) {
      return "已结算，账单进行了核实,并支付成功的";
    }
    return "挂起: 存在争议/无法系统结算";

  }

  private UserProfileDTO getBdUserProfile(TeamBillCycleDTO billCycle) {

    Long userId = businessDevelopmentTeamService.getUserIdByTeamId(billCycle.getTeamId());
    if (Objects.isNull(userId)) {
      return null;
    }

    UserProfileDTO userProfile = userProfileInnerConvertor.toUserProfileDTO(
        userProfileGateway.getByUserId(userId)
    );
    if (Objects.isNull(userProfile)) {
      return null;
    }
    return userProfile;
  }

  private UserProfileDTO getTeamOwnUser(Long ownUserId) {

    UserProfileDTO userProfile = userProfileInnerConvertor.toUserProfileDTO(
        userProfileGateway.getByUserId(ownUserId));
    if (Objects.isNull(userProfile)) {
      return null;
    }
    return userProfile;
  }

  private Set<Long> getMemberUserIds(List<TeamMemberTarget> teamMembers) {
    return teamMembers.stream().map(TeamMemberTarget::getUserId).collect(
        Collectors.toSet());
  }

  private Map<String, TeamPolicyManager> mapRegionPolicyManager(
      TeamBillByConditionQryCmd param) {

    List<TeamPolicyManager> managerList = teamPolicyManagerService
        .listReleaseTeamPolicy(param.getSysOrigin(), param.getRegion());

    if (CollectionUtils.isEmpty(managerList)) {
      return Maps.newHashMap();
    }

    return managerList.stream().collect(Collectors.toMap(TeamPolicyManager::getRegion, v -> v));
  }

  private Set<Long> getTeamIds(List<TeamBillCycleDTO> billCycleList) {
    return billCycleList.stream().map(TeamBillCycleDTO::getTeamId).collect(
        Collectors.toSet());
  }

  private List<TeamMemberTarget> getTeamMemberTargets(TeamBillCycleDTO teamBillCycle) {
    return teamMemberTargetService.listByBillBelong(
        teamBillCycle.getTeamId(), teamBillCycle.getBillBelong());
  }


  private TeamProfile getTeamProfile(TeamBillCycleBackQryCmd query) {
    if (Objects.nonNull(query.getOwnUserId())) {
      return teamProfileService.getByOwnUserId(query.getOwnUserId());
    }
    return null;
  }


  private List<TeamBillCycleDTO> assembleTeamBillCycleVO(TeamBillCycleBackQryCmd query) {

    List<TeamBillCycle> teamBillCycles = teamBillCycleService.list(query);

    if (Objects.isNull(teamBillCycles)) {
      return Lists.newArrayList();
    }

    Map<Long, TeamProfile> teamProfileMap = teamProfileService.mapProfileByIds(
        teamBillCycles.stream().map(TeamBillCycle::getTeamId).collect(Collectors.toSet()));

    Set<String> regionIds = getRegionIds(teamBillCycles);

    Map<String, TeamPolicyManager> policyManagerMap = teamPolicyManagerService
        .mapRegionRelease(regionIds);

    return teamBillCycles.stream().map(teamBillCycle -> {

      TeamBillCycleDTO vo = teamInfraConvertor.toTeamBillCycleDTO(teamBillCycle);
      TeamProfile teamProfile =
              teamProfileMap.get(teamBillCycle.getTeamId());
      if (Objects.nonNull(teamProfile)) {

        TeamPolicyManager policyManager = policyManagerMap.get(teamProfile.getRegion());

        vo.setTeamProfile(teamInfraConvertor.toTeamProfileDTO(teamProfile));

        if (Objects.isNull(vo.getSettleResult()) || Objects.isNull(policyManager)) {

          List<TeamMemberTarget> teamMemberTargets = getTeamMemberTargets(teamBillCycle);

          List<TeamBillMemberTarget> teamBillMemberTargets = TeamBillCycleUtils
                  .calculatorPolicyTarget(teamMemberTargets, policyManager);

          // 结算账单.
          vo.setSettleResult(new TeamBillSettleResultDTO()
                  .setPolicy(teamInfraConvertor.toTeamPolicyManagerDTO(policyManager))
                  .setWorkMembers(countWorkMembers(teamMemberTargets))
                  .setFinishMembers(teamBillMemberTargets.size())
                  .setMemberSalary(sumMemberSalary(teamBillMemberTargets))
                  .setOwnSalary(ownSalary(teamBillMemberTargets))
                  .setTotalSalary(ownTotalSalary(teamBillMemberTargets))
          );
        }
      }

      List<BillDiamondBalance> billDiamondBalances = billDiamondBalanceService
              .getEntityByBillBelongAndTeamId(teamBillCycle.getSysOrigin(), teamBillCycle.getBillBelong(), teamBillCycle.getTeamId());

      BigDecimal totalSalary = vo.getSettleResult().getTotalSalary();
      BigDecimal redeemedDiamondsSalary = redeemedDiamondsSalary(billDiamondBalances);
      log.warn(totalSalary + "");
      log.warn(redeemedDiamondsSalary + "");
      vo.getSettleResult().setRedeemedDiamondsSalary(redeemedDiamondsSalary);
      vo.getSettleResult().setRemainingDiamondsSalary(totalSalary.subtract(redeemedDiamondsSalary).setScale(0, RoundingMode.DOWN));

      return vo;
    }).collect(Collectors.toList());
  }


  private int countWorkMembers(List<TeamMemberTarget> teamMemberTargets) {
    return CollectionUtils.isNotEmpty(teamMemberTargets) ? teamMemberTargets.size() : 0;
  }

  private BigDecimal sumMemberSalary(List<TeamBillMemberTarget> teamBillMemberTargets) {
    return teamBillMemberTargets.stream().map(TeamBillMemberTarget::getMemberSalary)
        .reduce(BigDecimal.ZERO, BigDecimal::add)
        .setScale(2, RoundingMode.DOWN);
  }


  private BigDecimal ownSalary(List<TeamBillMemberTarget> teamBillMemberTargets) {
    return teamBillMemberTargets.stream().map(TeamBillMemberTarget::getOwnSalary)
        .reduce(BigDecimal.ZERO, BigDecimal::add)
        .setScale(2, RoundingMode.DOWN);
  }


  private Set<String> getRegionIds(List<TeamBillCycle> teamBillCycles) {
    return teamBillCycles.stream().map(TeamBillCycle::getRegion).collect(Collectors.toSet());
  }

  private BigDecimal ownTotalSalary(List<TeamBillMemberTarget> teamBillMemberTargets) {
    return teamBillMemberTargets.stream().map(TeamBillMemberTarget::getTotalSalary)
        .reduce(BigDecimal.ZERO, BigDecimal::add)
        .setScale(2, RoundingMode.DOWN);
  }

  private BigDecimal redeemedDiamondsSalary(List<BillDiamondBalance> billDiamondBalances) {
    BigDecimal bigDecimal = billDiamondBalances.stream().map(BillDiamondBalance::getConsumptionPoints)
            .reduce(BigDecimal.ZERO, BigDecimal::add)
            .setScale(0, RoundingMode.DOWN);
    BigDecimal AgentBigDecimal = billDiamondBalances.stream().map(BillDiamondBalance::getAgentConsumptionPoints)
            .reduce(BigDecimal.ZERO, BigDecimal::add)
            .setScale(0, RoundingMode.DOWN);
    return bigDecimal.add(AgentBigDecimal);
  }

  private List<TeamMemberTarget> getTeamMemberTargets(TeamBillCycle teamBillCycle) {
    return teamMemberTargetService.listByBillBelong(
        teamBillCycle.getTeamId(), teamBillCycle.getBillBelong());
  }
}
