package com.red.circle.console.app.service.app.team;

import com.red.circle.common.business.enums.OperationUserOrigin;
import com.red.circle.console.app.convertor.UserAppConvertor;
import com.red.circle.console.app.convertor.team.TeamAppConvertor;
import com.red.circle.console.app.dto.clienobject.team.TeamApplicationProcessApprovalCO;
import com.red.circle.console.infra.database.rds.entity.admin.User;
import com.red.circle.console.infra.database.rds.service.admin.UserService;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.other.inner.endpoint.team.agency.AgentTeamClient;
import com.red.circle.other.inner.endpoint.team.target.TeamProfileClient;
import com.red.circle.other.inner.model.cmd.team.TeamApplicationProcessApprovalQryCmd;
import com.red.circle.other.inner.model.dto.agency.agency.TeamApplicationProcessApprovalDTO;
import com.red.circle.other.inner.model.dto.agency.agency.TeamMemberDTO;
import com.red.circle.other.inner.enums.team.TeamApplicationType;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.other.inner.endpoint.user.user.UserProfileClient;
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 java.util.stream.Stream;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

/**
 * 团队申请审核日志.
 *
 * @author pengshigang on 2022/12/19
 */
@Service
@RequiredArgsConstructor
public class TeamApplicationProcessApprovalBackServiceImpl implements
    TeamApplicationProcessApprovalBackService {

  private final UserService userService;
  private final AgentTeamClient agentTeamClient;
  private final TeamAppConvertor teamAppConvertor;
  private final UserAppConvertor userAppConvertor;
  private final UserProfileClient userProfileClient;
  private final TeamProfileClient teamProfileClient;

  @Override
  public List<TeamApplicationProcessApprovalCO> listByCondition(
      TeamApplicationProcessApprovalQryCmd query) {

    if (Objects.nonNull(query.getAssociateId()) && Objects
        .equals(query.getType(), TeamApplicationType.TEAM)) {
      TeamMemberDTO teamMember = ResponseAssert.requiredSuccess(
          agentTeamClient.getByMemberId(query.getAssociateId()));
      if (Objects.isNull(teamMember)) {
        return List.of();
      }
      query.setAssociateId(teamMember.getTeamId());
    }

    List<TeamApplicationProcessApprovalDTO> approvalList = ResponseAssert.requiredSuccess(
        teamProfileClient
            .listProcessApprovalByCondition(query));

    if (CollectionUtils.isEmpty(approvalList)) {
      return List.of();
    }

    Set<Long> userIds = getUserIds(approvalList);
    if (CollectionUtils.isEmpty(userIds)) {
      return List.of();
    }

    Map<Long, User> userMap = getSysUsers(userIds);
    Map<Long, UserProfileDTO> userProfileMap = getUserProfiles(userIds);

    return approvalList.stream().map(approval -> {

      TeamApplicationProcessApprovalCO approvalVO = teamAppConvertor.toTeamApplicationProcessApprovalCO(
          approval);
      if (Objects.isNull(approvalVO)) {
        return approvalVO;
      }

      approvalVO.setBeProcessUser(userProfileMap.get(approvalVO.getBeProcessUserId()));

      if (Objects.equals(approvalVO.getCreateUserOrigin(), OperationUserOrigin.BACK.getValue())) {
        approvalVO.setCreateSysUser(
            userAppConvertor.toAdminUserCO(userMap.get(approvalVO.getCreateUser())));
      }

      if (Objects.equals(approvalVO.getCreateUserOrigin(), OperationUserOrigin.APP.getValue())) {
        approvalVO.setCreateUserProfile(userProfileMap.get(approvalVO.
            getCreateUser()));
      }
      return approvalVO;

    }).filter(Objects::nonNull).collect(Collectors.toList());

  }

  private Set<Long> getUserIds(List<TeamApplicationProcessApprovalDTO> approvalList) {
    return Stream.of(approvalList.stream().map(TeamApplicationProcessApprovalDTO::
            getBeProcessUserId).collect(Collectors.toSet()),
        approvalList.stream().map(TeamApplicationProcessApprovalDTO::getCreateUser).collect(
            Collectors.toSet())).flatMap(Collection::stream).collect(Collectors.toSet());
  }

  private Map<Long, UserProfileDTO> getUserProfiles(Set<Long> ids) {

    return ResponseAssert.requiredSuccess(userProfileClient.mapByUserIds(ids));
  }

  private Map<Long, User> getSysUsers(Set<Long> ids) {

    return userService.mapBackUser(ids);
  }

}
