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

import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.CommonErrorCode;
import com.red.circle.other.app.dto.cmd.room.RoomMikeTypeCmd;
import com.red.circle.other.infra.database.cache.service.other.EnumConfigCacheService;
import com.red.circle.other.infra.database.mongo.entity.live.RoomSetting;
import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService;
import com.red.circle.other.infra.database.rds.enums.live.MikeTypeEnum;
import com.red.circle.other.infra.database.rds.enums.live.MikeTypeExpireTypeEnum;
import com.red.circle.other.infra.database.rds.service.live.RoomMikeTypeService;
import com.red.circle.other.infra.database.rds.service.sys.MikeTypeConfigService;
import com.red.circle.other.inner.asserts.PropsErrorCode;
import com.red.circle.other.inner.enums.config.EnumConfigKey;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.num.ArithmeticUtils;
import com.red.circle.tool.core.text.StringUtils;
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;

/**
 * 购买活动房间麦类型
 *
 * @author zongpubin on 2023/3/24 18:09
 */
@Component
@RequiredArgsConstructor
public class RoomMikeTypePurchasingCmdExe {

  private final WalletGoldClient walletGoldClient;
  private final RoomMikeTypeService roomMikeTypeService;
  private final MikeTypeConfigService mikeTypeConfigService;
  private final EnumConfigCacheService enumConfigCacheService;
  private final RoomProfileManagerService roomProfileManagerService;


  public BigDecimal execute(RoomMikeTypeCmd cmd) {

    if (StringUtils.isBlank(cmd.getDuration()) && Objects.equals(cmd.getMikeType(),
        "SPECIAL_MIKE")) {
      // 校验是否已购买过特殊麦位类型
      boolean isPurchaseMikeType = roomMikeTypeService.isPurchaseMikeType(cmd.requiredReqUserId(),
          cmd.getMikeType());

      ResponseAssert.isFalse(PropsErrorCode.ROOM_MIKE_TYPE_EXIST_DONT_BUY_ERROR,
          isPurchaseMikeType);

      BigDecimal roomMikeAmount = enumConfigCacheService.getValueBigDecimal(
          EnumConfigKey.ROOM_MIKE_AMOUNT_ASWAT,
          cmd.requireReqSysOrigin()
      );

      // 2040 配置错误
      ResponseAssert.isTrue(CommonErrorCode.CONFIGURATION_ERROR,
          ArithmeticUtils.gtZero(roomMikeAmount));

      // 扣款
      WalletReceiptResDTO receiptRes = ResponseAssert.requiredSuccess(
          walletGoldClient.changeBalance(GoldReceiptCmd.builder()
              .appExpenditure()
              .userId(cmd.getReqUserId())
              .eventId(Objects.toString(roomMikeAmount))
              .sysOrigin(cmd.requireReqSysOrigin())
              .origin(GoldOrigin.PURCHASE_ROOM_MIKE)
              .amount(roomMikeAmount)
              .build())
      );

      // 5006 活动房间特殊麦位购买失败
      ResponseAssert.isTrue(PropsErrorCode.BUY_FALL,
          roomMikeTypeService.save(cmd.requiredReqUserId(), cmd.requireReqSysOrigin(),
              cmd.getMikeType(), roomMikeAmount));

      // 修改房间麦位信息
      roomProfileManagerService.updateSelectiveSettingByUserId(cmd.requiredReqUserId(),
          new RoomSetting()
              .setRoomSpecialMikeType(cmd.getMikeType())
              .setRoomSpecialMikeExpireType(MikeTypeExpireTypeEnum.PERMANENT.name())
      );

      return receiptRes.getBalance().getDollarAmount();
    } else {

      // 校验是否已购买过特殊麦位类型还未过期
      boolean isPurchaseMikeTypeNotExpire = roomMikeTypeService.isPurchaseMikeType(
          cmd.requiredReqUserId(),
          cmd.getMikeType(), MikeTypeExpireTypeEnum.TEMPORARY.name());

      ResponseAssert.isFalse(PropsErrorCode.ROOM_MIKE_TYPE_EXIST_DONT_BUY_ERROR,
          isPurchaseMikeTypeNotExpire);

      // 校验是否已购买过特殊麦位类型
      boolean isPurchaseMikeType = roomMikeTypeService.isPurchaseMikeType(cmd.requiredReqUserId(),
          cmd.getMikeType(), MikeTypeExpireTypeEnum.PERMANENT.name());

      ResponseAssert.isFalse(PropsErrorCode.ROOM_MIKE_TYPE_EXIST_DONT_BUY_ERROR,
          isPurchaseMikeType);

      BigDecimal roomMikeAmount = mikeTypeConfigService.getMikeTypeAmount(cmd.getMikeType(),
          cmd.getDuration(), cmd.requireReqSysOriginEnum());

      // 配置错误
      ResponseAssert.isTrue(CommonErrorCode.CONFIGURATION_ERROR,
          ArithmeticUtils.gtZero(roomMikeAmount));

      // 扣款
      WalletReceiptResDTO receiptRes = ResponseAssert.requiredSuccess(
          walletGoldClient.changeBalance(GoldReceiptCmd.builder()
              .appExpenditure()
              .userId(cmd.getReqUserId())
              .eventId(Objects.toString(roomMikeAmount))
              .sysOrigin(cmd.requireReqSysOrigin())
              .origin(GoldOrigin.PURCHASE_ROOM_MIKE)
              .amount(roomMikeAmount)
              .build())
      );

      // 活动房间特殊麦位购买失败
      ResponseAssert.isTrue(PropsErrorCode.BUY_FALL,
          roomMikeTypeService.save(cmd.requiredReqUserId(), cmd.requireReqSysOrigin(),
              cmd.getMikeType(), cmd.getDuration(), roomMikeAmount));

      // 修改房间麦位信息
      if (Objects.equals(cmd.getDuration(), MikeTypeEnum.FIFTEEN_DAYS.name())) {
        roomProfileManagerService.updateSelectiveSettingByUserId(cmd.requiredReqUserId(),
            new RoomSetting()
                .setRoomSpecialMikeType(cmd.getMikeType())
                .setRoomSpecialMikeExpireTime(TimestampUtils.nowPlusDays(15))
                .setRoomSpecialMikeExpireType(MikeTypeExpireTypeEnum.TEMPORARY.name())
        );
      } else if (Objects.equals(cmd.getDuration(), MikeTypeEnum.FOREVER.name())) {
        roomProfileManagerService.updateSelectiveSettingByUserId(cmd.requiredReqUserId(),
            new RoomSetting()
                .setRoomSpecialMikeType(cmd.getMikeType())
                .setRoomSpecialMikeExpireTime(TimestampUtils.now())
                .setRoomSpecialMikeExpireType(MikeTypeExpireTypeEnum.PERMANENT.name())
        );
      }
      return receiptRes.getBalance().getDollarAmount();

    }


  }
}
