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

import com.red.circle.common.business.core.enums.ApprovalStatusEnum;
import com.red.circle.console.app.convertor.bank.BankAppConvertor;
import com.red.circle.console.app.dto.clienobject.user.UserBankCardCO;
import com.red.circle.console.inner.error.ConsoleErrorCode;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.other.inner.endpoint.user.user.UserProfileClient;
import com.red.circle.wallet.inner.error.BankErrorCode;
import com.red.circle.wallet.inner.endpoint.bank.UserBankCardClient;
import com.red.circle.wallet.inner.model.cmd.UserBankCardBackQryCmd;
import com.red.circle.wallet.inner.model.cmd.UserBankCardCmd;
import com.red.circle.wallet.inner.model.cmd.UserBankCardPassCmd;
import com.red.circle.wallet.inner.model.dto.UserBankCardDTO;
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 pengshigang on 2022/12/5
 */
@Service
@RequiredArgsConstructor
public class UserBankCardBackServiceImpl implements UserBankCardBackService {

  private final UserBankCardClient bankCardClient;
  private final BankAppConvertor bankAppConvertor;
  private final UserProfileClient userProfileClient;

  @Override
  public void add(UserBankCardCmd param) {

    ResponseAssert.isFalse(BankErrorCode.REPEAT_BANK_CARD_ERROR,
        ResponseAssert.requiredSuccess(
            bankCardClient.existBankCard(param.getUserId(), param.getCardType(),
                param.getCardNo())));

    param.setId(IdWorkerUtils.getId());
    param.setDel(Boolean.FALSE);
    param.setStatus(ApprovalStatusEnum.PASS.name());
    param.setSysOrigin(param.getSysOrigin());
    bankCardClient.addBankCard(param);
  }

  @Override
  public void update(UserBankCardCmd param) {
    bankCardClient.updateBankCard(param);
  }

  @Override
  public List<UserBankCardCO> listByUserId(Long userId) {
    return bankAppConvertor.toListUserBankCardCO(
        ResponseAssert.requiredSuccess(bankCardClient.listByUserId(userId)));
  }

  @Override
  public List<UserBankCardDTO> listPassBankCard(Long type) {
    return ResponseAssert.requiredSuccess(bankCardClient.listPassByUserId(type));
  }

  @Override
  public void use(Long id, Long currentUidLong) {

    UserBankCardDTO bankCard = ResponseAssert.requiredSuccess(bankCardClient.getById(id));
    ResponseAssert.notNull(ConsoleErrorCode.NOT_FOUND_RECORD, bankCard);
    ResponseAssert.isFalse(ConsoleErrorCode.NOT_FOUND_RECORD, bankCard.getDel());
    ResponseAssert.isTrue(BankErrorCode.NOT_APPROVED_ERROR,
        Objects.equals(ApprovalStatusEnum.PASS.name(), bankCard.getStatus()));
    ResponseAssert.requiredSuccess(
        bankCardClient.useBankCard(id, bankCard.getUserId(), currentUidLong));
  }

  @Override
  public void deleteById(Long id, Long currentUidLong) {
    UserBankCardDTO bankCard = ResponseAssert.requiredSuccess(bankCardClient.getById(id));
    ResponseAssert.notNull(ConsoleErrorCode.NOT_FOUND_RECORD, bankCard);
    ResponseAssert.isFalse(ConsoleErrorCode.NOT_FOUND_RECORD, bankCard.getDel());
    bankCardClient.deleteByIdByUserId(id, bankCard.getUserId(), currentUidLong);
  }

  @Override
  public void pass(Set<Long> ids, Long currentUidLong) {
    bankCardClient.pass(
        new UserBankCardPassCmd().setCurrentUidLong(currentUidLong).setIds(ids));
  }

  @Override
  public void notPass(Set<Long> ids, Long currentUidLong) {
    bankCardClient.notPass(
        new UserBankCardPassCmd().setCurrentUidLong(currentUidLong).setIds(ids));
  }

  @Override
  public PageResult<UserBankCardCO> pageQuery(UserBankCardBackQryCmd query) {

    PageResult<UserBankCardDTO> bankCardDTOPageResult = ResponseAssert.requiredSuccess(
        bankCardClient.pageQuery(query));
    PageResult<UserBankCardCO> pageResult = bankCardDTOPageResult.convert(
        bankAppConvertor::toUserBankCardCO);

    if (pageResult.getTotal() <= 0) {
      return pageResult;
    }

    Map<Long, UserProfileDTO> userProfileMap = getUserProfileMap(
        pageResult.getRecords().stream().toList());
    if (CollectionUtils.isEmpty(userProfileMap)) {
      return pageResult;
    }

    pageResult.setRecords(pageResult.getRecords().stream().map(card -> {

      UserProfileDTO userProfile = userProfileMap.get(card.getUserId());
      if (Objects.isNull(userProfile)) {
        return null;
      }

      card.setUserProfile(userProfile);
      return card;
    }).filter(Objects::nonNull).collect(Collectors.toList()));

    return pageResult;
  }


  private Map<Long, UserProfileDTO> getUserProfileMap(List<UserBankCardCO> userBankCards) {
    return ResponseAssert.requiredSuccess(userProfileClient.mapByUserIds(
        userBankCards.stream().map(UserBankCardCO::getUserId).collect(Collectors.toSet())));
  }


}
