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

import com.red.circle.common.business.dto.cmd.AppExtCommand;
import com.red.circle.common.business.dto.cmd.app.AppIdLongCmd;
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.other.app.common.props.GroupRewardPoolCommon;
import com.red.circle.other.infra.common.activity.PropsActivitySendCommon;
import com.red.circle.other.infra.common.activity.send.SendRewardSingle;
import com.red.circle.other.infra.database.cache.service.other.CumulativeRechargeCacheService;
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.inner.asserts.PropsErrorCode;
import com.red.circle.other.inner.enums.activity.PropsActivityTypeEnum;
import com.red.circle.other.inner.model.dto.activity.props.ActivityRewardProps;
import com.red.circle.other.inner.model.dto.activity.rule.CumulativeRechargeContent;
import com.red.circle.tool.core.num.ArithmeticUtils;
import com.red.circle.tool.core.num.NumUtils;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import com.red.circle.other.inner.asserts.user.UserErrorCode;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

/**
 * 累计充值抽奖.
 *
 * @author pengshigang on 2022/3/29
 */
@Component
@RequiredArgsConstructor
public class CumulativeRechargeLotteryExe {

  private final PropsActivitySendCommon activitySendCommon;
  private final GroupRewardPoolCommon groupRewardPoolManager;
  private final CumulativeRechargeCacheService cumulativeRechargeCacheService;

  public ActivityRewardProps execute(AppIdLongCmd cmd) {

    List<PropsActivityRuleConfig> activityRuleConfigs = getActivityRuleConfigs(cmd);
    //今天充值金额
    BigDecimal todayRecharge = BigDecimal.valueOf(cumulativeRechargeCacheService
        .getTodayRechargeScore(cmd.getReqUserId()));
    // 2046 不可领取
    ResponseAssert.isFalse(PropsErrorCode.UNCLAIMABLE, !ArithmeticUtils
        .gt(todayRecharge, BigDecimal.ZERO));

    String jsonString = activityRuleConfigs.get(cmd.getId().intValue() - 1).getJsonData();

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

    ResponseAssert.isTrue(PropsErrorCode.UNCLAIMABLE,
        todayRecharge.compareTo(cumulativeRechargeContent.getQuantity()) >= 0);

    //校验是否已领取
    ResponseAssert.isTrue(UserErrorCode.PROCESSED_TODAY,
        Objects.equals(cumulativeRechargeCacheService
            .markTodayAwarded(cmd.getReqUserId(), cmd.getId()), Boolean.TRUE));

    List<List<ActivityRewardProps>> rewardPropsList = groupRewardPoolManager
        .listRewardProps(cmd.requireReqSysOriginEnum(),
            PropsActivityTypeEnum.CUMULATIVE_RECHARGE_LOTTERY);
    ResponseAssert.notEmpty(CommonErrorCode.DATA_ERROR, rewardPropsList);

    List<ActivityRewardProps> propsList = rewardPropsList.get(cmd.getId().intValue() - 1);
    ResponseAssert.notEmpty(CommonErrorCode.DATA_ERROR, propsList);

    ActivityRewardProps rewardPropsCO = propsList
        .get(NumUtils.randomBetweenRepeatedly(0, propsList.size() - 1));
    ResponseAssert.notNull(CommonErrorCode.DATA_ERROR, rewardPropsCO);

    sendReward(cmd, rewardPropsCO);

    return rewardPropsCO;

  }

  private List<PropsActivityRuleConfig> getActivityRuleConfigs(AppIdLongCmd cmd) {
    List<PropsActivityRuleConfig> configs = groupRewardPoolManager
        .listByActivityTypeLimit(cmd.requireReqSysOriginEnum(),
            PropsActivityTypeEnum.CUMULATIVE_RECHARGE_LOTTERY);
    ResponseAssert.notEmpty(CommonErrorCode.DATA_ERROR, configs);
    ResponseAssert.isTrue(CommonErrorCode.DATA_ERROR, configs.size() >= 3);
    return configs;
  }

  private void sendReward(AppExtCommand cmd, ActivityRewardProps rewardPropsCO) {
    activitySendCommon.sendActivitySingle(SendRewardSingle.builder()
        .rewardConfig(new PropsActivityRewardConfig()
            .setContent(rewardPropsCO.getContent())
            .setDetailType(
                Optional.ofNullable(rewardPropsCO.getDetailType()).orElse(rewardPropsCO.getType()))
            .setQuantity(rewardPropsCO.getQuantity())
            .setType(rewardPropsCO.getType())
            .setGroupId(rewardPropsCO.getGroupId())
        )
        .sysOrigin(cmd.requireReqSysOriginEnum())
        .origin(SendPropsOrigin.CUMULATIVE_RECHARGE_REWARDS)
        .acceptUserId(cmd.getReqUserId())
        .trackId(IdWorkerUtils.getId())
        .build());
  }

}
