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.SendPropsOrigin;
import com.red.circle.component.redis.service.RedisService;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.CommonErrorCode;
import com.red.circle.other.domain.gateway.props.ActivitySourceGroupGateway;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
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.mongo.entity.team.team.TeamMember;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamProfile;
import com.red.circle.other.infra.database.mongo.service.activity.ActivityAgentAnchorCountService;
import com.red.circle.other.infra.database.mongo.service.activity.ActivityRewardReceiveMarkService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamProfileService;
import com.red.circle.other.inner.asserts.PropsErrorCode;
import com.red.circle.other.inner.asserts.team.TeamErrorCode;
import com.red.circle.other.inner.asserts.user.UserErrorCode;
import com.red.circle.other.inner.enums.activity.PropsActivityTypeEnum;
import com.red.circle.other.inner.model.dto.activity.props.ActivityPropsRule;
import com.red.circle.other.inner.model.dto.activity.rule.CommonContent;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

/**
 * 代理主播领取奖励.
 *
 * @author pengshigang on 2023/2/27
 */
@Component
@RequiredArgsConstructor
public class ActivityAgentAnchorReceiveCmdExe {

  private final RedisService redisService;
  private final TeamMemberService teamMemberService;
  private final TeamProfileService teamProfileService;
  private final UserProfileGateway userProfileGateway;
  private final PropsActivitySendCommon propsActivitySendCommon;
  private final ActivitySourceGroupGateway activitySourceGroupGateway;
  private final ActivityAgentAnchorCountService activityAgentAnchorCountService;
  private final ActivityRewardReceiveMarkService activityRewardReceiveMarkService;

  public void execute(AppIdLongCmd cmd) {
    userProfileGateway.removeCacheAll(cmd.requiredReqUserId());
    ActivityPropsRule ruleConfig = activitySourceGroupGateway.getByRuleId(cmd.getId());

    // 1034 没有找到映射信息
    ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_MAPPING_INFO, ruleConfig);

    CommonContent commonContent = CommonContent.serializable(ruleConfig.getJsonData());
    // 2040 配置错误
    ResponseAssert.notNull(CommonErrorCode.CONFIGURATION_ERROR, commonContent);

    Integer dateNumber = null;
    Long businessId = cmd.getReqUserId();
    // 代理主播数量激励奖励
    Long count = 0L;
    if (PropsActivityTypeEnum.ACTIVE_AGENT_ANCHOR_COUNT_REWARD.name()
        .equals(ruleConfig.getActivityType())) {
      TeamProfile teamProfile = getTeamProfile(cmd);
      if (Objects.nonNull(teamProfile.getCounter())) {
        count = Optional.ofNullable(teamProfile.getCounter().getMemberQuantity())
            .orElse(0L);
      }
      businessId = teamProfile.getId();
      ResponseAssert.isFalse(CommonErrorCode.NON_REPEATABLE, activityRewardReceiveMarkService
          .exist(teamProfile.getId(), ruleConfig.getActivityType(), null, ruleConfig.getId()));
    }

    // 代理名下主播累计月目标奖励
    if (PropsActivityTypeEnum.ACTIVE_AGENT_MONTH_TARGET_REWARD.name()
        .equals(ruleConfig.getActivityType())) {
      dateNumber = getThisMonthDate();
      TeamProfile teamProfile = getTeamProfile(cmd);
      count = activityAgentAnchorCountService
          .getCountQuantity(teamProfile.getId(),
              PropsActivityTypeEnum.ACTIVE_AGENT_MONTH_TARGET_REWARD.name(), dateNumber);
      ResponseAssert.isFalse(CommonErrorCode.NON_REPEATABLE, activityRewardReceiveMarkService
          .exist(teamProfile.getId(), ruleConfig.getActivityType(), dateNumber,
              ruleConfig.getId()));
      businessId = teamProfile.getId();
    }

    // 主播月目标奖励
    if (PropsActivityTypeEnum.ACTIVE_ANCHOR_MONTH_TARGET_REWARD.name()
        .equals(ruleConfig.getActivityType())) {
      dateNumber = getThisMonthDate();
      TeamMember teamMember = getMember(cmd);
      count = activityAgentAnchorCountService
          .getCountQuantity(teamMember.getMemberId(),
              PropsActivityTypeEnum.ACTIVE_ANCHOR_MONTH_TARGET_REWARD.name(), dateNumber);
      ResponseAssert.isFalse(CommonErrorCode.NON_REPEATABLE, activityRewardReceiveMarkService
          .exist(teamMember.getMemberId(), ruleConfig.getActivityType(), dateNumber,
              ruleConfig.getId()));
    }
    // 主播日目标奖励
    if (PropsActivityTypeEnum.ACTIVE_ANCHOR_DAY_TARGET_REWARD.name()
        .equals(ruleConfig.getActivityType())) {
      dateNumber = getThisDayDate();
      TeamMember teamMember = getMember(cmd);
      count = activityAgentAnchorCountService
          .getCountQuantity(teamMember.getMemberId(),
              PropsActivityTypeEnum.ACTIVE_ANCHOR_DAY_TARGET_REWARD.name(), dateNumber);

      // 1035 不可重复领取
      ResponseAssert.isFalse(CommonErrorCode.NON_REPEATABLE, activityRewardReceiveMarkService
          .exist(teamMember.getMemberId(), ruleConfig.getActivityType(), dateNumber,
              ruleConfig.getId()));
    }

    ResponseAssert.isTrue(PropsErrorCode.UNCLAIMABLE, count >= commonContent.getQuantity());

    // 防止重复触发领取 3分钟后可重试领取
    ResponseAssert.isTrue(UserErrorCode.AWARD_RECEIVED, redisService.setIfAbsent(
        GoldOrigin.valueOf(ruleConfig.getActivityType()) + ":" + cmd.getReqUserId() + ":"
            + cmd.getId(), 3, TimeUnit.MINUTES));

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

    // 标记为已领取
    activityRewardReceiveMarkService
        .add(businessId, ruleConfig.getActivityType(), dateNumber, ruleConfig.getId(),
            cmd.getReqUserId());
  }

  private TeamProfile getTeamProfile(AppIdLongCmd cmd) {
    TeamProfile teamProfile =
        teamProfileService.getAvailableByOwnUserId(cmd.getReqUserId());
    ResponseAssert.notNull(TeamErrorCode.TEAM_NOT_FOUND, teamProfile);
    return teamProfile;
  }

  private TeamMember getMember(AppIdLongCmd cmd) {
    TeamMember teamMember = teamMemberService.getByMemberId(cmd.getReqUserId());
    ResponseAssert.notNull(TeamErrorCode.TEAM_NOT_FOUND, teamMember);
    return teamMember;
  }

  private Integer getThisMonthDate() {
    return ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt();
  }

  private Integer getThisDayDate() {
    return ZonedDateTimeAsiaRiyadhUtils.nowDateToInt();
  }
}
