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.app.service.task.TaskService;
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.OtherErrorCode;
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.tool.core.sequence.IdWorkerUtils;
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;
  private final TaskService taskService;

  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.isFalse(GiftErrorCode.GIFT_NOT_FOUND, Boolean.TRUE.equals(giftConfig.getDel()));

    // 判断版本号从而保证使用幸运礼物必须升级版本
    ResponseAssert.isTrue(CommonErrorCode.NOT_ACCEPT_REQUEST,
        Objects.equals(giftConfig.getGiftTab(), GiftTabEnum.LUCKY_GIFT.name()) ||
                Objects.equals(giftConfig.getGiftTab(), GiftTabEnum.MAGIC.name()));

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

    boolean luckyGift = GiftTabEnum.LUCKY_GIFT.name().equals(giftConfig.getGiftTab());
    boolean magicGift = GiftTabEnum.MAGIC.name().equals(giftConfig.getGiftTab());
    boolean freeGift = giftConfig.getGiftCandy().compareTo(BigDecimal.ZERO) == 0;
    String businessId = IdWorkerUtils.getIdStr();

    if (magicGift) {
      ResponseAssert.isFalse(GiftErrorCode.MAGIC_GIFT_QUANTITY_ERROR, cmd.getQuantity() > 1);
    }

    WalletReceiptResDTO receipt = null;
    BigDecimal balance;
    if (freeGift) {
      balance = walletGoldClient.getBalance(cmd.requiredReqUserId()).getBody().getDollarAmount();
      log.info("赠送幸运礼物金额为0,余额为 {}", balance);
      if (!luckyGift) {
        return balance;
      }
    } else {
      receipt = consumeCandy(cmd, giftConfig);
      balance = receipt.getBalance().getDollarAmount();
    }

    // 礼物处理mq 魔法礼物不处理，放到中奖后处理
    if (!magicGift) {
      Long trackId = Objects.nonNull(receipt) ? receipt.getAssetRecordId() : Long.parseLong(businessId);
      giftMqMessage.sendGift(
          Objects.toString(trackId),
          giftAppConvertor.toGiveAwayGiftBatchEvent(cmd, giftConfig, trackId)
      );
    }

    // 抽奖mq
    if (luckyGift) {
      gameLuckyGiftCommon.sendMq(
          cmd,
          giftConfig.getStandardId(),
          businessId,
          Objects.nonNull(receipt) ? Objects.toString(receipt.getAssetRecordId()) : null,
          giftConfig.getGiftCandy(),
          freeGift
      );
    } else {
      gameLuckyGiftCommon.sendMq(cmd, giftConfig.getStandardId());
    }

    userProfileGateway.removeCache(cmd.requiredReqUserId());

    // 检查是否未完成任务
    Boolean taskStatus = taskService.checkTaskStatus(cmd.getReqUserId(), 8L, null);
    if (taskStatus) {
      taskMqMessage.sendTask(TaskApprovalEvent.builder()
              .taskId(8)
              .quantity(cmd.getQuantity())
              .userId(cmd.getReqUserId())
              .build());
    }

    return balance;
  }

  /**
   * 付钱.
   */
  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.");

  }

}
