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

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.common.gift.GameLuckyGiftCommon;
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.asserts.RoomErrorCode;
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.wallet.inner.endpoint.wallet.WalletGoldClient;
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
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 pengshigang on 2023/08/04
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LuckyGiftGiveCmdExe {

  private final GiftMqMessage giftMqMessage;
  private final GiftAppConvertor giftAppConvertor;
  private final WalletGoldClient walletGoldClient;
  private final GiftCacheService giftCacheService;
  private final UserProfileGateway userProfileGateway;
  private final GameLuckyGiftCommon gameLuckyGiftCommon;
  private final TaskMqMessage taskMqMessage;

  public BigDecimal execute(GiveAwayGiftBatchCmd cmd) {

    ResponseAssert.notNull(RoomErrorCode.ROOM_NOT_EXISTS, cmd.getRoomId());

    GiftConfigDTO giftConfig = giftCacheService.getById(cmd.getGiftId());

    ResponseAssert.notNull(GiftErrorCode.GIFT_NOT_FOUND, giftConfig);

    // 判断版本号从而保证使用幸运礼物必须升级版本
    ResponseAssert.isTrue(CommonErrorCode.NOT_ACCEPT_REQUEST,
        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;
    }
    // 付钱
    WalletReceiptResDTO receipt = consumeCandy(cmd, giftConfig);

    // 礼物处理mq
    giftMqMessage.sendGift(receipt.getAssetRecordId().toString(),
        giftAppConvertor.toGiveAwayGiftBatchEvent(cmd, giftConfig, receipt.getAssetRecordId()));

    // 抽奖mq
    gameLuckyGiftCommon.sendMq(cmd, giftConfig.getStandardId());

    userProfileGateway.removeCache(cmd.requiredReqUserId());

    taskMqMessage.sendTask(TaskApprovalEvent.builder()
        .taskId(8)
        .quantity(cmd.getQuantity())
        .userId(cmd.getReqUserId())
        .build());

    return receipt.getBalance().getDollarAmount();
  }

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

    if (Objects.equals(giftConfig.getType(), GiftCurrencyType.GOLD.name())) {
      // 消耗金币
      return ResponseAssert.requiredSuccess(
          walletGoldClient.changeBalance(GoldReceiptCmd.builder()
              .appExpenditure()
              .eventId(giftConfig.getId())
              .userId(cmd.requiredReqUserId())
              .sysOrigin(cmd.requireReqSysOrigin())
              .origin(GoldOrigin.LUCKY_GIFT)
              .amount(cmd.calculateConsumeGolds(giftConfig.getGiftCandy()))
              .build())
      );
    }

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

  }

}
