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

import com.red.circle.common.business.dto.cmd.app.AppIdLongCmd;
import com.red.circle.common.business.enums.PropsActivityRewardEnum;
import com.red.circle.common.business.enums.SendPropsOrigin;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.CommonErrorCode;
import com.red.circle.order.inner.endpoint.UserRechargeCountClient;
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
import com.red.circle.other.infra.common.activity.PropsActivitySendCommon;
import com.red.circle.other.infra.common.activity.send.SendRewardGroup;
import com.red.circle.other.infra.database.rds.entity.activity.PropsActivityRewardConfig;
import com.red.circle.other.infra.database.rds.entity.activity.PropsActivityRuleConfig;
import com.red.circle.other.infra.database.rds.entity.props.PropsSourceRecord;
import com.red.circle.other.infra.database.rds.entity.user.user.UserActivityRewardReceiveRecord;
import com.red.circle.other.infra.database.rds.entity.user.user.UserCustomGiftRecord;
import com.red.circle.other.infra.database.rds.service.activity.PropsActivityRewardConfigService;
import com.red.circle.other.infra.database.rds.service.activity.PropsActivityRuleConfigService;
import com.red.circle.other.infra.database.rds.service.props.PropsSourceRecordService;
import com.red.circle.other.infra.database.rds.service.user.user.UserActivityRewardReceiveRecordService;
import com.red.circle.other.infra.database.rds.service.user.user.UserCustomGiftRecordService;
import com.red.circle.other.inner.asserts.PropsErrorCode;
import com.red.circle.other.inner.model.dto.activity.rule.CumulativeRechargeContent;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.LocalDateUtils;
import com.red.circle.tool.core.num.ArithmeticUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 累计充值领取奖励.
 *
 * @author pengliang on 2021/4/22
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class CumulativeRechargeReceiveRewardCmdExe {

  private final UserRegionGateway userRegionGateway;
  private final PropsActivitySendCommon activitySendCommon;
  private final UserRechargeCountClient userRechargeCountClient;
  private final PropsSourceRecordService propsSourceRecordService;
  private final UserCustomGiftRecordService userCustomGiftRecordService;
  private final PropsActivityRuleConfigService propsActivityRuleConfigService;
  private final PropsActivityRewardConfigService propsActivityRewardConfigService;
  private final UserActivityRewardReceiveRecordService activityRewardReceiveRecordService;


  public void execute(AppIdLongCmd cmd) {

    PropsActivityRuleConfig ruleConfig = propsActivityRuleConfigService.getById(cmd.getId());
    // 1034 没有找到映射信息
    ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_MAPPING_INFO, ruleConfig);

    CumulativeRechargeContent cumulativeRechargeContent = CumulativeRechargeContent
        .serializable(ruleConfig.getJsonData());

    // 2040 配置错误
    ResponseAssert.isTrue(CommonErrorCode.CONFIGURATION_ERROR,
        Objects.nonNull(cumulativeRechargeContent) && ArithmeticUtils
            .gt(cumulativeRechargeContent.getQuantity(), BigDecimal.ZERO));

    // 1035 不可重复领取
    ResponseAssert.isFalse(CommonErrorCode.NON_REPEATABLE, activityRewardReceiveRecordService
        .existsThisMonth(cmd.getReqUserId(), ruleConfig.getId()));

    BigDecimal monthlyRecharge = ResponseAssert.requiredSuccess(userRechargeCountClient
        .getThisMonthTotalPersonalRecharge(cmd.getReqUserId()));

    // 2046 不可领取
    ResponseAssert.isFalse(PropsErrorCode.UNCLAIMABLE,
        Objects.isNull(monthlyRecharge) || !ArithmeticUtils
            .gt(monthlyRecharge, BigDecimal.ZERO));

    activitySendCommon.sendActivityGroup(SendRewardGroup.builder()
        .trackId(ruleConfig.getId())
        .sysOrigin(cmd.requireReqSysOriginEnum())
        .acceptUserId(cmd.getReqUserId())
        .resourceGroupId(ruleConfig.getResourceGroupId())
        .origin(SendPropsOrigin.CUMULATIVE_RECHARGE_REWARDS)
        .build());

    activityRewardReceiveRecordService.save(new UserActivityRewardReceiveRecord()
        .setUserId(cmd.getReqUserId())
        .setRechargeDate(LocalDateUtils.nowFirstDayOfMonthToInteger())
        .setActivityId(cmd.getId())
    );

    // 记录领取专属礼物
    customGiftRecord(ruleConfig.getResourceGroupId(), cmd, cumulativeRechargeContent.getQuantity());
  }

  private void customGiftRecord(Long groupId, AppIdLongCmd cmd, BigDecimal quantity) {
    List<PropsActivityRewardConfig> rewardConfigs = propsActivityRewardConfigService.listByGroupId(
        groupId);

    if (CollectionUtils.isEmpty(rewardConfigs)) {
      return;
    }
    // 过滤自定义(只读)
    List<PropsActivityRewardConfig> filterRewardConfigs = rewardConfigs.stream()
        .filter(rewardConfig -> Objects.equals(rewardConfig.getType(),
            PropsActivityRewardEnum.CUSTOMIZE.name())).toList();

    if (CollectionUtils.isEmpty(filterRewardConfigs)) {
      return;
    }

    for (PropsActivityRewardConfig filterRewardConfig : filterRewardConfigs) {
      PropsSourceRecord props = propsSourceRecordService.getPropsById(
          Long.valueOf(filterRewardConfig.getContent()));
      if (Objects.nonNull(props) && Objects.equals(props.getCode(), "custom_gift")) {
        userCustomGiftRecordService.save(new UserCustomGiftRecord()
            .setUserId(cmd.getReqUserId())
            .setSysOrigin(cmd.getReqSysOrigin().getOrigin())
            .setRegions(userRegionGateway.getRegionId(cmd.getReqUserId()))
            .setApproveStatus(Boolean.FALSE)
            .setUploadResource(Boolean.FALSE)
            .setQuantity(CollectionUtils.isNotEmpty(
                StringUtils.splitAsList(filterRewardConfig.getRemark(), "*")) ? Integer.valueOf(
                StringUtils.splitAsList(filterRewardConfig.getRemark(), "*").get(0)) : 0)
            .setRechargeDate(LocalDateUtils.nowThisMonthToInteger())
            .setAmount(quantity.intValue()));

      }

    }


  }

}
