package com.red.circle.order.app.listener;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.red.circle.common.business.core.enums.ReceiptType;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.common.business.enums.DiamondOrigin;
import com.red.circle.common.business.enums.SendPropsOrigin;
import com.red.circle.component.mq.MessageEventProcess;
import com.red.circle.component.mq.MessageEventProcessDescribe;
import com.red.circle.component.mq.config.RocketMqMessageListener;
import com.red.circle.component.mq.service.Action;
import com.red.circle.component.mq.service.ConsumerMessage;
import com.red.circle.component.mq.service.MessageListener;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.mq.business.model.event.pay.BuySuccessEvent;
import com.red.circle.mq.business.model.event.pay.PurchaseProductEvent;
import com.red.circle.mq.rocket.business.streams.BuySuccessSink;
import com.red.circle.other.inner.endpoint.activity.CumulativeRechargeClient;
import com.red.circle.other.inner.endpoint.activity.PropsActivityClient;
import com.red.circle.other.inner.endpoint.sys.EnumConfigClient;
import com.red.circle.other.inner.enums.activity.PropsActivityTypeEnum;
import com.red.circle.other.inner.enums.config.EnumConfigKey;
import com.red.circle.other.inner.model.cmd.activity.SendActivityRewardCmd;
import com.red.circle.other.inner.model.dto.activity.props.ActivityPropsRule;
import com.red.circle.other.inner.model.dto.user.UserOneTimeTaskDTO;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.tool.core.json.JacksonUtils;
import com.red.circle.tool.core.num.ArithmeticUtils;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import com.red.circle.tool.core.text.StringUtils;
import com.red.circle.other.inner.endpoint.user.user.InviteUserClient;
import com.red.circle.other.inner.endpoint.user.user.UserExpandClient;
import com.red.circle.other.inner.endpoint.user.user.UserOneTimeTaskClient;
import com.red.circle.other.inner.endpoint.user.user.UserProfileClient;
import com.red.circle.other.inner.model.dto.user.InviteUserRewardRecordDTO;
import com.red.circle.wallet.inner.endpoint.wallet.WalletDiamondClient;
import com.red.circle.wallet.inner.model.cmd.DiamondReceiptCmd;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 用户充值成功监听.
 *
 * @author pengliang on 2020/8/6
 */
@Slf4j
@RocketMqMessageListener(groupId = BuySuccessSink.INPUT, tag = BuySuccessSink.TAG)
@RequiredArgsConstructor
public class BuySuccessListener implements MessageListener {

  private final InviteUserClient inviteUserClient;
  private final EnumConfigClient enumConfigClient;
  private final UserExpandClient userExpandClient;
  private final UserProfileClient userProfileClient;
  private final PropsActivityClient propsActivityClient;
  private final WalletDiamondClient walletDiamondClient;
  private final MessageEventProcess messageEventProcess;
  private final UserOneTimeTaskClient userOneTimeTaskClient;
  private final CumulativeRechargeClient cumulativeRechargeClient;

  @Override
  public Action consume(ConsumerMessage message) {
    return messageEventProcess.consume(
        MessageEventProcessDescribe.builder()
            .logTag("语音房会话")
            .consumeMsgTimeoutMinute(15)
            .repeatConsumeMinute(15)
            .repeatConsumeTag("BuySuccess")
            .checkConsumeTag(BuySuccessSink.TAG)
            .message(message)
            .build(),
        BuySuccessEvent.class,
        this::execute);
  }

  private void execute(BuySuccessEvent eventBody) {
    if (!ArithmeticUtils.gt(eventBody.getCandyQuantity(), BigDecimal.ZERO)
        || Objects.equals(eventBody.getTrialPeriod(), Boolean.TRUE)) {
      return;
    }

    userExpandClient.updatePurchasingToTrue(eventBody.getUserId());
    userProfileClient.removeCache(eventBody.getUserId());

    //累计今日充值，每日累计充值抽奖活动
    cumulativeRechargeClient.incrTodayRechargeScore(
        eventBody.getAcceptUserId(), eventBody.getProductConfig().getUnitPrice().doubleValue());


      //被邀请人充值邀请人获得佣金
      inviteUserClient.processRechargeCommission(eventBody.getCandyQuantity(),
              eventBody.getSysOrigin(),
              eventBody.getUserId());

      completedFirstCharge(eventBody.getUserId(), eventBody.getSysOrigin());
  }

  private void completedFirstCharge(Long userId, String sysOrigin) {
      UserProfileDTO userProfileDTO = userProfileClient.getByUserId(userId).getBody();
      Duration duration = Duration.between(userProfileDTO.getCreateTime().toLocalDateTime(), LocalDateTime.now());
      if (duration.toDays() >= 7) {
          return;
      }

      ResultResponse<UserOneTimeTaskDTO> response = userOneTimeTaskClient.queryCompletedFirstCharge(userId, sysOrigin);
      if (response.checkSuccess()) {
          if (response.getBody() == null) {
              userOneTimeTaskClient.completedFirstCharge(userId, sysOrigin);

              // 发送首充奖励
              List<ActivityPropsRule> body = propsActivityClient.listRule(SysOriginPlatformEnum.valueOf(sysOrigin),
                      PropsActivityTypeEnum.FIRST_CHARGE_REWARD).getBody();
              if (body != null) {
                  ActivityPropsRule ruleConfig = body.get(0);

                  propsActivityClient.sendActivityReward(
                          new SendActivityRewardCmd()
                                  .setTrackId(ruleConfig.getId())
                                  .setOrigin(SendPropsOrigin.FIRST_CHARGE_REWARD)
                                  .setSysOrigin(SysOriginPlatformEnum.valueOf(ruleConfig.getSysOrigin()))
                                  .setSourceGroupId(ruleConfig.getResourceGroupId())
                                  .setAcceptUserId(userId)
                  );
                  userProfileClient.removeCacheAll(userId);
              }
          }
      }
  }

  private void handleVoiceSystemRechargeRewards(BuySuccessEvent cmd) {
    if (!isVoice(cmd)) {
      return;
    }
    Long rewardsUserId = inviteUserClient.getUserIdByInviteUserId(cmd.getUserId()).getBody();

    if (Objects.isNull(rewardsUserId)) {
      return;
    }

    if (Objects.equals(userExpandClient.checkPurchasing(cmd.getUserId()).getBody(), Boolean.TRUE)) {
      BigDecimal rewardAmount = enumConfigClient
          .getValueBigDecimal(EnumConfigKey.INVITED_USER_EACH_RECHARGE, cmd.getSysOrigin())
          .getBody();
      BigDecimal rewardQuantity = rewardAmount.divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN)
          .multiply(cmd.getCandyQuantity()).setScale(0, RoundingMode.DOWN);
      if (!ArithmeticUtils.gteZero(rewardQuantity)) {
        log.warn("没有找到有效奖励:{}", JacksonUtils.toJson(cmd));
        return;
      }
      sendInviteUserReward(cmd,
          rewardsUserId,
          rewardQuantity,
          DiamondOrigin.INVITED_USER_EACH_RECHARGE);
      return;
    }

    BigDecimal invitedQuantity = enumConfigClient
        .toDiamondQuantity(EnumConfigKey.INVITED_USER_FIRST_RECHARGE_REWARD, cmd.getSysOrigin())
        .getBody();
    if (!ArithmeticUtils.gtZero(invitedQuantity)) {
      log.warn("没有找到有效首冲奖励:{}", JacksonUtils.toJson(cmd));
      return;
    }

    sendInviteUserReward(cmd,
        rewardsUserId,
        invitedQuantity,
        DiamondOrigin.INVITE_FIRST_RECHARGE);

  }

  private void sendInviteUserReward(BuySuccessEvent cmd, Long acceptUserId,
      BigDecimal rewardQuantity, DiamondOrigin origin) {
    inviteUserClient.addRewardRecord(
        new InviteUserRewardRecordDTO()
            .setUserId(acceptUserId)
            .setInviteUserId(cmd.getUserId())
            .setOrigin(origin.name())
            .setOriginName(origin.getDesc())
            .setQuantity(rewardQuantity)
    );

    walletDiamondClient.changeBalance(
        new DiamondReceiptCmd()
            .setConsumeId(IdWorkerUtils.getIdStr())
            .setSysOrigin(SysOriginPlatformEnum.valueOf(cmd.getSysOrigin()))
            .setType(ReceiptType.INCOME)
            .setTrackId(IdWorkerUtils.getId())
            .setUserId(acceptUserId)
            .setOriginUserId(cmd.getUserId())
            .setOrigin(origin)
            .setAmount(rewardQuantity)
            .setCreateTime(cmd.getBuyDateTime())
    );
  }

  private boolean isVoice(BuySuccessEvent cmd) {
    return SysOriginPlatformEnum.getVoiceSystems()
        .contains(SysOriginPlatformEnum.valueOf(cmd.getSysOrigin()));
  }

  private BuySuccessEvent checkParamException(BuySuccessEvent cmd) {
    boolean isException = Objects.isNull(cmd)
        || Objects.isNull(cmd.getUserId())
        || Objects.isNull(cmd.getPurchaseHistoryId())
        || StringUtils.isBlank(cmd.getSysOrigin());
    if (isException) {
      throw new IllegalArgumentException("param is error:" + JacksonUtils.toJson(cmd));
    }
    return cmd;
  }

}
