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

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.app.dto.cmd.task.CheckInRewardCmd;
import com.red.circle.other.infra.common.activity.PropsActivitySendCommon;
import com.red.circle.other.infra.common.props.PropsSendCommon;
import com.red.circle.other.infra.database.cache.service.other.CheckInCacheService;
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.service.activity.PropsActivityRewardConfigService;
import com.red.circle.other.infra.database.rds.service.activity.PropsActivityRuleConfigService;
import com.red.circle.other.inner.asserts.GameErrorCode;
import com.red.circle.other.inner.model.cmd.material.PrizeDescribe;
import com.red.circle.other.inner.model.cmd.material.PrizeDescribeRewardCmd;
import com.red.circle.other.infra.utils.ZonedDateTimeUtils;
import com.red.circle.tool.core.date.ZonedId;
import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

/**
 * 每日打卡奖励-信息.
 *
 * @author zongpubin on 2023/10/19
 */
@Service
@AllArgsConstructor
public class CheckInExe {

  private final RedisService redisService;
  private final CheckInCacheService checkInCacheService;
  private final PropsActivitySendCommon propsActivitySendCommon;
  private final PropsActivityRuleConfigService propsActivityRuleConfigService;
  private final PropsActivityRewardConfigService propsActivityRewardConfigService;
  private final PropsSendCommon propsSendCommon;

  public Integer execute(CheckInRewardCmd cmd) {

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

    String lockKey = "CHECK_IN_DAILY_REWARD:" + cmd.getReqUserId();

    try {

      ResponseAssert.isTrue(CommonErrorCode.NOT_REPEATABLE,
          redisService.lock(lockKey, 30));

      ResponseAssert.isFalse(GameErrorCode.CHECKED_IN,
          checkInCacheService.checkDailyCheckIn(cmd.getReqUserId()));

      ResponseAssert.isFalse(GameErrorCode.CHECKED_IN,
          Objects.equals(checkInCacheService.getCheckInDays(cmd.getReqUserId()), 7));

      // 累计打卡天数
      Long inDays = checkInCacheService.incrCheckInDays(cmd.getReqUserId(), getExpiredTime(cmd));
      checkInCacheService.markDailyCheckIn(cmd.getReqUserId());

/*    不再根据资源组发，根据资源组顺序一个一个发
      propsActivitySendCommon.sendActivityGroup(SendRewardGroup.builder()
          .trackId(cmd.getId())
          .sysOrigin(cmd.requireReqSysOriginEnum())
          .acceptUserId(cmd.getReqUserId())
          .resourceGroupId(cmd.getResourceGroupId())
          .origin(SendPropsOrigin.DAILY_REGISTER)
          .build());*/

      List<PropsActivityRewardConfig> configs = propsActivityRewardConfigService.listByGroupId(cmd.getResourceGroupId());
      ResponseAssert.notEmpty(CommonErrorCode.NOT_FOUND_MAPPING_INFO, configs);


      // 根据星期几获取对应的奖品配置（星期几就是第几个配置，索引需要减1）
      int configIndex = Math.min(inDays.intValue() - 1, configs.size() - 1);
      ResponseAssert.isTrue(CommonErrorCode.NOT_FOUND_MAPPING_INFO, configIndex >= 0 && configIndex < configs.size());
      
      PropsActivityRewardConfig config = configs.get(configIndex);

      propsSendCommon.send(new PrizeDescribeRewardCmd()
          .setTrackId(cmd.getId())
          .setAcceptUserId(cmd.getReqUserId())
          .setOrigin(SendPropsOrigin.DAILY_REGISTER)
          .setSysOrigin(cmd.requireReqSysOriginEnum())
          .setPrizes(Collections.singletonList(new PrizeDescribe()
              .setTrackId(config.getGroupId())
              .setType(config.getType())
              .setDetailType(config.getDetailType())
              .setContent(config.getContent())
              .setQuantity(config.getQuantity())))
      );


      return checkInCacheService.getCheckInDays(cmd.getReqUserId());

    } finally {
      redisService.unlock(lockKey);
    }
  }

  private long getExpiredTime(CheckInRewardCmd cmd) {
    Duration duration = getDuration();
    long expiredTime = duration.plusDays(1).toMillis();
    if (Objects.equals(6, checkInCacheService.getCheckInDays(cmd.getReqUserId()))) {
      expiredTime = duration.toMillis();
    }
    return expiredTime;
  }

  private Duration getDuration() {
    return ZonedDateTimeUtils.todayInterval(ZonedId.ASIA_RIYADH.getZonedId(), 0);
  }


}
