package com.red.circle.other.app.command.gift;

import com.red.circle.common.business.core.enums.ReceiptType;
import com.red.circle.common.business.enums.DiamondOrigin;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.CommonErrorCode;
import com.red.circle.framework.core.response.ResponseErrorCode;
import com.red.circle.mq.business.model.event.task.TaskApprovalEvent;
import com.red.circle.mq.rocket.business.producer.GiftMqMessage;
import com.red.circle.mq.rocket.business.producer.TaskMqMessage;
import com.red.circle.other.app.convertor.material.GiftAppConvertor;
import com.red.circle.other.app.dto.cmd.gift.GiveAwayGiftBatchCmd;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.infra.database.cache.service.other.GiftCacheService;
import com.red.circle.other.inner.asserts.GiftErrorCode;
import com.red.circle.other.inner.enums.material.GiftCurrencyType;
import com.red.circle.other.inner.enums.material.GiftTabEnum;
import com.red.circle.other.inner.model.dto.material.GiftConfigDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.LocalDateTimeUtils;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import com.red.circle.wallet.inner.endpoint.wallet.WalletDiamondClient;
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
import com.red.circle.wallet.inner.model.cmd.DiamondReceiptCmd;
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
import com.red.circle.wallet.inner.model.dto.WalletReceiptDTO;
import com.red.circle.wallet.inner.model.dto.WalletReceiptResDTO;
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
import java.math.BigDecimal;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * 赠送礼物
 *
 * @author pengliang on 2020/11/18
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class GiftGiveAwayBatchCmdExe {

  private final GiftMqMessage giftMqMessage;
  private final GiftAppConvertor giftAppConvertor;
  private final WalletGoldClient walletGoldClient;
  private final GiftCacheService giftCacheService;
  private final TaskMqMessage taskMqMessage;
  private final UserProfileGateway userProfileGateway;
  private final WalletDiamondClient walletDiamondClient;

  public BigDecimal execute(GiveAwayGiftBatchCmd cmd) {

    GiftConfigDTO giftConfig = giftCacheService.getById(cmd.getGiftId());
      log.warn("GiftGiveAwayBatchCmdExe{}", giftConfig);

    // 未找到礼物
    ResponseAssert.notNull(GiftErrorCode.GIFT_NOT_FOUND, giftConfig);

    // 判断赠送是否为幸运礼物,是则必须升级版本,新版本此接口就不再接受幸运礼物
    ResponseAssert.isFalse(GiftErrorCode.NOT_SUPPORTED_GIFT_TYPE,
        Objects.equals(giftConfig.getGiftTab(), GiftTabEnum.LUCKY_GIFT.name()));

    // 过滤赠送人非法值
    ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR,
        CollectionUtils.isNotEmpty(cmd.filterAcceptUserId()));

    if (giftConfig.getGiftCandy().equals(new BigDecimal("0.00"))) {
      BigDecimal dollarAmount = walletGoldClient.getBalance(cmd.requiredReqUserId()).getBody().getDollarAmount();
      log.info("赠送普通礼物金额为0,余额为 {}", dollarAmount);
      return dollarAmount;
    }
    // 付钱
    WalletReceiptDTO receipt = consumeCandy(cmd, giftConfig);
      log.warn("GiftGiveAwayBatchCmdExe{}", receipt);

    giftMqMessage.sendGift(receipt.getConsumeId().toString(),
        giftAppConvertor.toGiveAwayGiftBatchEvent(cmd, giftConfig, receipt.getConsumeId()));
    userProfileGateway.removeCache(cmd.requiredReqUserId());
    taskMqMessage.sendTask(TaskApprovalEvent.builder()
            .taskId(2)
            .userId(cmd.getReqUserId())
            .day(LocalDateTimeUtils.nowFormat("yyyy-MM-dd"))
            .build());

    return receipt.getBalance();
  }

  /**
   * 付钱.
   */
  private WalletReceiptDTO consumeCandy(GiveAwayGiftBatchCmd cmd, GiftConfigDTO giftConfig) {

    if (isGiftTypeEqFree(giftConfig)) {
      // 获取余额
      return new WalletReceiptDTO()
          .setConsumeId(IdWorkerUtils.getId())
          .setProcessAmount(BigDecimal.ZERO)
          .setBalance(
              ResponseAssert.requiredSuccess(walletGoldClient.getBalance(cmd.requiredReqUserId()))
                  .getDollarAmount());

    }

    if (isGiftTypeEqGold(giftConfig)) {
      BigDecimal amount = cmd.calculateConsumeGolds(giftConfig.getGiftCandy());
      // 消耗金币
      WalletReceiptResDTO receiptRes = walletGoldClient.changeBalance(GoldReceiptCmd.builder()
          .appExpenditure()
          .userId(cmd.requiredReqUserId())
          .eventId(giftConfig.getId())
          .sysOrigin(cmd.requireReqSysOrigin())
          .origin(GoldOrigin.GIVE_GIFT + "_" + giftConfig.getGiftTab())
          .amount(amount)
          .closeDelayAsset()
          .build()).getBody();
      return new WalletReceiptDTO()
          .setConsumeId(receiptRes.getAssetRecordId())
          .setBalance(receiptRes.getBalance().getDollarAmount())
          .setProcessAmount(amount);
    }

    if (isGiftTypeEqDiamond(giftConfig)) {
      // 消费积分
      return walletDiamondClient.changeBalance(new DiamondReceiptCmd()
          .setConsumeId(Objects.toString(giftConfig.getId()))
          .setType(ReceiptType.EXPENDITURE)
          .setTrackId(giftConfig.getId())
          .setUserId(cmd.requiredReqUserId())
          .setSysOrigin(cmd.requireReqSysOriginEnum())
          .setOrigin(DiamondOrigin.GIVE_GIFT)
          .setAmount(cmd.calculateConsumeGolds(giftConfig.getGiftCandy()))
          .setCreateTime(TimestampUtils.now())
      ).getBody();
    }

    // 类型不在范围
    ResponseAssert.failure(CommonErrorCode.TYPE_IS_NOT_IN_SCOPE);
    throw new IllegalArgumentException("param error.");
  }

  private boolean isGiftTypeEqDiamond(GiftConfigDTO giftConfigInfo) {
    return Objects.equals(giftConfigInfo.getType(), GiftCurrencyType.DIAMOND.name());
  }

  private boolean isGiftTypeEqGold(GiftConfigDTO giftConfigInfo) {
    return Objects.equals(giftConfigInfo.getType(), GiftCurrencyType.GOLD.name());
  }

  private boolean isGiftTypeEqFree(GiftConfigDTO giftConfigInfo) {
    return Objects.equals(giftConfigInfo.getType(), GiftCurrencyType.FREE.name());
  }


}
