package com.red.circle.wallet.inner.service.wallet.impl;

import com.red.circle.framework.core.dto.ReqSysOrigin;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.text.StringUtils;
import com.red.circle.wallet.app.command.bank.UserBankExchangeGoldCmdExe;
import com.red.circle.wallet.app.dto.cmd.UserBankExchangeGoldCmd;
import com.red.circle.wallet.domain.gateway.WalletDiamondGateway;
import com.red.circle.wallet.domain.wallet.DiamondReceipt;
import com.red.circle.wallet.infra.database.rds.service.diamond.DiamondBalanceService;
import com.red.circle.wallet.infra.database.rds.service.diamond.DiamondRunningWaterService;
import com.red.circle.wallet.inner.convertor.WalletInnerConvertor;
import com.red.circle.wallet.inner.model.cmd.DiamondReceiptCmd;
import com.red.circle.wallet.inner.model.cmd.UserDiamondBalanceQryCmd;
import com.red.circle.wallet.inner.model.cmd.UserDiamondOriginQryCmd;
import com.red.circle.wallet.inner.model.cmd.UserDiamondRunWaterQryCmd;
import com.red.circle.wallet.inner.model.dto.DiamondBalanceDTO;
import com.red.circle.wallet.inner.model.dto.UserDiamondOriginDTO;
import com.red.circle.wallet.inner.model.dto.UserDiamondRunWaterDTO;
import com.red.circle.wallet.inner.model.dto.WalletReceiptDTO;
import com.red.circle.wallet.inner.service.wallet.WalletDiamondClientService;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

/**
 * @author pengliang on 2023/5/26
 */
@Service
@RequiredArgsConstructor
public class WalletDiamondClientServiceImpl implements WalletDiamondClientService {

  private static final Logger log = LoggerFactory.getLogger(WalletDiamondClientServiceImpl.class);
  private final WalletInnerConvertor walletInnerConvertor;
  private final WalletDiamondGateway walletDiamondGateway;
  private final DiamondBalanceService diamondBalanceService;
  private final DiamondRunningWaterService diamondRunningWaterService;
  private final UserBankExchangeGoldCmdExe userBankExchangeGoldCmdExe;

  @Override
  public BigDecimal getBalance(Long userId) {
    return walletDiamondGateway.getBalance(userId);
  }

  @Override
  public WalletReceiptDTO changeBalance(DiamondReceiptCmd cmd) {
    log.warn("com:" + cmd);
    DiamondReceipt receipt = walletInnerConvertor.toDiamondReceipt(cmd);

    receipt.setOrigin(
        Objects.nonNull(cmd.getOrigin())
            ? cmd.getOrigin().name()
            : cmd.getCustomizeOrigin()
    );

    receipt.setOriginDesc(
        StringUtils.isBlank(cmd.getCustomizeOriginDesc())
            ? cmd.getOrigin().getDesc()
            : cmd.getCustomizeOriginDesc()
    );

    return walletInnerConvertor.toWalletReceiptDTO(walletDiamondGateway.changeBalance(receipt));
  }

  @Override
  public PageResult<DiamondBalanceDTO> pageUserDiamondBalance(UserDiamondBalanceQryCmd query) {
    return diamondBalanceService.pageUserDiamondBalance(query)
        .convert(walletInnerConvertor::toUserDiamondBalanceDTO);
  }

  @Override
  public PageResult<UserDiamondRunWaterDTO> pageUserDiamondRunWater(
      UserDiamondRunWaterQryCmd query) {
    return diamondRunningWaterService.pageUserDiamondRunWater(query)
        .convert(walletInnerConvertor::toUserDiamondRunWaterDTO);
  }

  @Override
  public PageResult<UserDiamondOriginDTO> pageUserDiamondOriginDetails(
      UserDiamondOriginQryCmd query) {
    return diamondRunningWaterService.pageUserDiamondOriginDetails(query)
        .convert(walletInnerConvertor::toUserDiamondOriginDTO);
  }

  @Override
  public Map<Long, BigDecimal> mapBalance(Collection<Long> userIds) {
    if (CollectionUtils.isEmpty(userIds)) {
      return CollectionUtils.newHashMap();
    }
    return walletDiamondGateway.mapBalance(userIds.stream().toList());
  }

  @Override
  public Map<Long, BigDecimal> salaryMapBalance(Collection<Long> userIds) {
    if (CollectionUtils.isEmpty(userIds)) {
      return CollectionUtils.newHashMap();
    }
    return walletDiamondGateway.salaryMapBalance(userIds.stream().toList());
  }

  @Override
  public void autoExchangeGold(Long userId, BigDecimal amount) {
    UserBankExchangeGoldCmd cmd = new UserBankExchangeGoldCmd();
    cmd.setAmount(amount);
    cmd.setReqUserId(userId);
    cmd.setReqTime(new Date());
    cmd.setReqSysOrigin(ReqSysOrigin.of("LIKEI"));
    log.warn("【钻石转金币定时器】用户-{} 自动兑换金币量 {}", userId, cmd);
    try {
      userBankExchangeGoldCmdExe.executeDiamond(cmd);
    } catch (Exception e) {
      log.warn("【钻石转金币定时器】用户-{} 自动兑换金币异常 {}", userId, e.getMessage());
    }
  }

}
