package com.red.circle.other.app.command.game.luckybox;


import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.CommonErrorCode;
import com.red.circle.other.app.common.game.GameLuckyBoxCommon;
import com.red.circle.other.app.dto.clientobject.game.GameLuckyBoxAwardCO;
import com.red.circle.other.app.dto.cmd.game.GameLuckyBoxAwardCmd;
import com.red.circle.other.infra.database.mongo.entity.live.RoomProfile;
import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService;
import com.red.circle.other.infra.database.rds.entity.game.GameLuckyBoxTimeConfig;
import com.red.circle.other.infra.database.rds.entity.gift.GiftBackpack;
import com.red.circle.other.infra.database.rds.entity.gift.GiftConfig;
import com.red.circle.other.infra.database.rds.service.game.GameLuckyBoxTimeConfigService;
import com.red.circle.other.infra.database.rds.service.gift.GiftBackpackService;
import com.red.circle.other.infra.database.rds.service.gift.GiftConfigService;
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 org.springframework.stereotype.Component;

/**
 * 新 luckyBox用户抽奖
 *
 * @author zongpubin on 2023/8/30
 */

@Component
@RequiredArgsConstructor
public class GameLuckyBoxAwardCmdExe {

  private final WalletGoldClient walletGoldClient;
  private final GiftConfigService giftConfigService;
  private final GiftBackpackService giftBackpackService;
  private final GameLuckyBoxCommon gameLuckyBoxCommon;
  private final RoomProfileManagerService roomProfileManagerService;
  private final GameLuckyBoxTimeConfigService gameLuckyBoxTimeConfigService;

  public GameLuckyBoxAwardCO execute(GameLuckyBoxAwardCmd cmd) {
    Integer awardNum = 0;
    BigDecimal balance = BigDecimal.ZERO;
    // 抽奖频数
    GameLuckyBoxTimeConfig timeConfig = gameLuckyBoxTimeConfigService.getById(cmd.getId());

    ResponseAssert.isFalse(CommonErrorCode.CONFIGURATION_ERROR, Objects.isNull(timeConfig));

    RoomProfile roomProfile = roomProfileManagerService.getProfileById(cmd.getRoomId());
    if (Objects.isNull(roomProfile)) {
      return null;
    }

    // 用户抽奖券数量
    GiftConfig giftConfig = giftConfigService.getByCode("lucky_box_gift-choujiangquan-3");

    if (Objects.isNull(giftConfig)) {
      return null;
    }

    GiftBackpack userGift = giftBackpackService.getUserGift(cmd.requiredReqUserId(),
        giftConfig.getId());
    if (Objects.nonNull(userGift)) {
      awardNum = userGift.calculationQuantity();
    }

    if (awardNum > 0) {

      if (timeConfig.getFrequency() - awardNum > 0) {
        balance = balance.add(consumeCandy(cmd, timeConfig.getConsumptionGold()));
      } else {
        giftBackpackService.consumerGifts(userGift.getId(), giftConfig.getId(),
            cmd.requiredReqUserId(), timeConfig.getFrequency());
        balance = balance.add(ResponseAssert.requiredSuccess(walletGoldClient.getBalance(
            cmd.requiredReqUserId())).getDollarAmount());
        timeConfig.setConsumptionGold(BigDecimal.ZERO);
      }

    } else {

      balance = balance.add(consumeCandy(cmd, timeConfig.getConsumptionGold()));
    }

    // 抽奖
    GameLuckyBoxAwardCO gameLuckyBoxAwardCO = gameLuckyBoxCommon.runLuckyBoxGame(timeConfig, cmd);
    gameLuckyBoxAwardCO.setBalance(balance);
    return gameLuckyBoxAwardCO;


  }


  private BigDecimal consumeCandy(GameLuckyBoxAwardCmd cmd, BigDecimal consumptionGold) {

    // 消耗金币
    WalletReceiptResDTO walletReceipt = ResponseAssert.requiredSuccess(
        walletGoldClient.changeBalance(GoldReceiptCmd.builder()
            .appExpenditure()
            .sysOrigin(cmd.getReqSysOrigin().getOrigin())
            .eventId(cmd.getId())
            .userId(cmd.requiredReqUserId())
            .origin(GoldOrigin.NEW_LUCKY_BOX_GAME)
            .amount(consumptionGold)
            .build()));
    return walletReceipt.getBalance().getDollarAmount();
  }
}
