package com.red.circle.game.fruit.application.command;

import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
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.dto.ResultResponse;
import com.red.circle.game.fruit.application.dto.cmd.GameFruitReceiveTaskAwardCmd;
import com.red.circle.game.fruit.application.dto.enums.MessageTypeTopic;
import com.red.circle.game.fruit.infrastructure.database.cache.service.GameFruitTaskCacheService;
import com.red.circle.game.fruit.infrastructure.database.entity.GameFruitTaskAwardConfig;
import com.red.circle.game.fruit.infrastructure.database.entity.GameFruitUserTaskReceive;
import com.red.circle.game.fruit.infrastructure.database.repository.GameFruitAwardRecordService;
import com.red.circle.game.fruit.infrastructure.database.repository.GameFruitTaskAwardConfigService;
import com.red.circle.game.fruit.infrastructure.database.repository.GameFruitUserDaysRankingService;
import com.red.circle.game.fruit.infrastructure.database.repository.GameFruitUserTaskReceiveService;
import com.red.circle.game.fruit.infrastructure.websocket.message.MessageSender;
import com.red.circle.game.fruit.infrastructure.websocket.message.TopicMessage;
import com.red.circle.game.fruit.inner.enums.GameFruitTaskEnum;
import com.red.circle.game.fruit.inner.error.GameFruitErrorCode;
import com.red.circle.other.inner.endpoint.activity.PropsActivityClient;
import com.red.circle.other.inner.model.cmd.activity.SendActivityRewardCmd;
import com.red.circle.tool.core.date.LocalDateUtils;
import com.red.circle.other.inner.asserts.user.UserErrorCode;
import com.red.circle.other.inner.endpoint.user.user.UserProfileClient;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 领取任务奖励
 *
 * @author zongpubin on 2023/12/18
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class GameFruitReceiveTaskAwardExe {

  private final RedisService redisService;
  private final MessageSender messageSender;
  private final UserProfileClient userProfileClient;
  private final PropsActivityClient propsActivityCnfClient;
  private final GameFruitTaskCacheService gameFruitTaskCacheService;
  private final GameFruitAwardRecordService gameFruitAwardRecordService;
  private final GameFruitUserDaysRankingService gameFruitUserDaysRankingService;
  private final GameFruitUserTaskReceiveService gameFruitUserTaskReceiveService;
  private final GameFruitTaskAwardConfigService gameFruitTaskAwardConfigService;

  public void execute(GameFruitReceiveTaskAwardCmd cmd) {

    String lockKey = "CHECK_IN_GAME_FRUIT_TASK_RECEIVE_REWARD:" + cmd.getUid();

    // 用户数据
    UserProfileDTO userProfileDTO = ResponseAssert.requiredSuccess(
        userProfileClient.getByUserId(cmd.getUid()));

    if (Objects.isNull(userProfileDTO)) {
      messageSender.sendTopic(
          TopicMessage.of(
              MessageTypeTopic.GAME_FRUIT_RECEIVE_TASK_AWARD_MSG.getTopicId(cmd.getUid()),
              ResultResponse.failure(
                  UserErrorCode.USER_INFO_NOT_FOUND)));
      return;
    }

    GameFruitTaskAwardConfig awardConfig = gameFruitTaskAwardConfigService.getById(
        cmd.getAwardId());

    if (Objects.isNull(awardConfig)) {
      messageSender.sendTopic(
          TopicMessage.of(
              MessageTypeTopic.GAME_FRUIT_RECEIVE_TASK_AWARD_MSG.getTopicId(cmd.getUid()),
              ResultResponse.failure(
                  GameFruitErrorCode.GAME_FRUIT_TASK_AWARD_INFO_NOT_FOUND)));
      return;
    }

    // 校验是否重复领取
    if (Boolean.TRUE.equals(checkReceive(awardConfig, cmd.getUid()))) {
      return;
    }
    // 校验是否达到领取目标
    if (Boolean.TRUE.equals(checkQuantity(cmd.getUid(), awardConfig))) {
      return;
    }

    try {
      if (redisService.lock(lockKey, 20)) {

        gameFruitUserTaskReceiveService.save(new GameFruitUserTaskReceive()
            .setAwardId(cmd.getAwardId())
            .setReceiveDate(getReceiveDate(awardConfig))
            .setSysOrigin(userProfileDTO.getOriginSys())
            .setUserId(cmd.getUid())
        );

        // 发送道具
        propsActivityCnfClient.sendActivityReward(new SendActivityRewardCmd()
            .setTrackId(cmd.getAwardId())
            .setSysOrigin(SysOriginPlatformEnum.valueOf(userProfileDTO.getOriginSys()))
            .setAcceptUserId(cmd.getUid())
            .setSourceGroupId(awardConfig.getResourceGroupId())
            .setOrigin(SendPropsOrigin.GAME_FRUIT_TASK_REWARD)
        );

        messageSender.sendTopic(
            TopicMessage.of(
                MessageTypeTopic.GAME_FRUIT_RECEIVE_TASK_AWARD_MSG.getTopicId(cmd.getUid()),
                ResultResponse.success(
                    GameFruitErrorCode.GAME_FRUIT_TASK_AWARD_RECEIVE_SUCCESS)));

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


  }

  private Boolean checkQuantity(Long userId, GameFruitTaskAwardConfig awardConfig) {

    if (Objects.equals(awardConfig.getTaskType(), GameFruitTaskEnum.WEEK_COMPETITION.name())) {
      Integer quantity = gameFruitTaskCacheService.getGameFruitTaskAward(userId,
          awardConfig.getTaskType());
      if (quantity < awardConfig.getQuantityDays()) {
        messageSender.sendTopic(
            TopicMessage.of(
                MessageTypeTopic.GAME_FRUIT_RECEIVE_TASK_AWARD_MSG.getTopicId(userId),
                ResultResponse.failure(
                    GameFruitErrorCode.GAME_FRUIT_TASK_AWARD_NOT_COMPLETED)));
        log.warn(
            "摩天轮游戏任务未满足,目标:" + quantity + ";quantity:" + awardConfig.getQuantityDays());
        return Boolean.TRUE;
      }

    }

    if (Objects.equals(awardConfig.getTaskType(),
        GameFruitTaskEnum.WINNING_ONE_OF_THE_PRIZES_ONE.name())) {
      Integer quantity = gameFruitTaskCacheService.getGameFruitTaskAward(userId,
          awardConfig.getTaskType());
      if (quantity < awardConfig.getQuantity()) {
        messageSender.sendTopic(
            TopicMessage.of(
                MessageTypeTopic.GAME_FRUIT_RECEIVE_TASK_AWARD_MSG.getTopicId(userId),
                ResultResponse.failure(
                    GameFruitErrorCode.GAME_FRUIT_TASK_AWARD_NOT_COMPLETED)));
        log.warn(
            "摩天轮游戏任务未满足,目标:" + quantity + ";quantity:" + awardConfig.getQuantity());
        return Boolean.TRUE;
      }

    }

    if (Objects.equals(awardConfig.getTaskType(),
        GameFruitTaskEnum.WINNING_ONE_OF_THE_PRIZES_TWO.name())) {
      Integer quantity = gameFruitTaskCacheService.getGameFruitTaskAward(userId,
          awardConfig.getTaskType());
      if (quantity < awardConfig.getQuantity()) {
        messageSender.sendTopic(
            TopicMessage.of(
                MessageTypeTopic.GAME_FRUIT_RECEIVE_TASK_AWARD_MSG.getTopicId(userId),
                ResultResponse.failure(
                    GameFruitErrorCode.GAME_FRUIT_TASK_AWARD_NOT_COMPLETED)));
        log.warn(
            "摩天轮游戏任务未满足,目标:" + quantity + ";quantity:" + awardConfig.getQuantity());
        return Boolean.TRUE;
      }

    }

    if (Objects.equals(awardConfig.getTaskType(),
        GameFruitTaskEnum.NUMBER_OF_WINNING_ROUNDS.name())) {
      Integer quantity = gameFruitTaskCacheService.getUserWinRounds(userId);
      if (quantity < awardConfig.getQuantity()) {
        messageSender.sendTopic(
            TopicMessage.of(
                MessageTypeTopic.GAME_FRUIT_RECEIVE_TASK_AWARD_MSG.getTopicId(userId),
                ResultResponse.failure(
                    GameFruitErrorCode.GAME_FRUIT_TASK_AWARD_NOT_COMPLETED)));
        log.warn(
            "摩天轮游戏任务未满足,目标:" + quantity + ";quantity:" + awardConfig.getQuantity());
        return Boolean.TRUE;
      }

    }

    if (Objects.equals(awardConfig.getTaskType(),
        GameFruitTaskEnum.NUMBER_OF_PROFIT_ROUNDS.name())) {
      long quantity = gameFruitAwardRecordService.countWeekWinRounds(userId);
      if (quantity < awardConfig.getQuantity()) {
        messageSender.sendTopic(
            TopicMessage.of(
                MessageTypeTopic.GAME_FRUIT_RECEIVE_TASK_AWARD_MSG.getTopicId(userId),
                ResultResponse.failure(
                    GameFruitErrorCode.GAME_FRUIT_TASK_AWARD_NOT_COMPLETED)));
        log.warn(
            "摩天轮游戏任务未满足,目标:" + quantity + ";quantity:" + awardConfig.getQuantity());
        return Boolean.TRUE;
      }

    }

    if (Objects.equals(awardConfig.getTaskType(),
        GameFruitTaskEnum.NUMBER_OF_PROFIT_COINS.name())) {
      Long quantity = gameFruitUserDaysRankingService.countWeekEarning(userId);
      if (quantity < awardConfig.getQuantity()) {
        messageSender.sendTopic(
            TopicMessage.of(
                MessageTypeTopic.GAME_FRUIT_RECEIVE_TASK_AWARD_MSG.getTopicId(userId),
                ResultResponse.failure(
                    GameFruitErrorCode.GAME_FRUIT_TASK_AWARD_NOT_COMPLETED)));
        log.warn(
            "摩天轮游戏任务未满足,目标:" + quantity + ";quantity:" + awardConfig.getQuantity());
        return Boolean.TRUE;
      }

    }

    if (Objects.equals(awardConfig.getTaskType(),
        GameFruitTaskEnum.NUMBER_OF_DAYS_WEEK.name())) {
      Long quantity = gameFruitUserDaysRankingService.countWeekPlayDays(userId);
      if (quantity < awardConfig.getQuantity()) {
        messageSender.sendTopic(
            TopicMessage.of(
                MessageTypeTopic.GAME_FRUIT_RECEIVE_TASK_AWARD_MSG.getTopicId(userId),
                ResultResponse.failure(
                    GameFruitErrorCode.GAME_FRUIT_TASK_AWARD_NOT_COMPLETED)));
        log.warn(
            "摩天轮游戏任务未满足,目标:" + quantity + ";quantity:" + awardConfig.getQuantity());
        return Boolean.TRUE;
      }

    }

    if (Objects.equals(awardConfig.getTaskType(),
        GameFruitTaskEnum.TASK_COMPLETE_DAY.name())) {
      Integer quantity = gameFruitTaskCacheService.getGameFruitTaskAward(userId,
          GameFruitTaskEnum.TASK_COMPLETE_DAY.name());
      if (quantity < 1) {
        messageSender.sendTopic(
            TopicMessage.of(
                MessageTypeTopic.GAME_FRUIT_RECEIVE_TASK_AWARD_MSG.getTopicId(userId),
                ResultResponse.failure(
                    GameFruitErrorCode.GAME_FRUIT_TASK_AWARD_NOT_COMPLETED)));
        log.warn(
            "摩天轮游戏任务未满足,目标:" + quantity + ";quantity:" + awardConfig.getQuantity());
        return Boolean.TRUE;
      }

    }

    if (Objects.equals(awardConfig.getTaskType(),
        GameFruitTaskEnum.TASK_COMPLETE_WEEK.name())) {
      Integer quantity = gameFruitTaskCacheService.getGameFruitTaskAward(userId,
          GameFruitTaskEnum.TASK_COMPLETE_WEEK.name());
      if (quantity < 1) {
        messageSender.sendTopic(
            TopicMessage.of(
                MessageTypeTopic.GAME_FRUIT_RECEIVE_TASK_AWARD_MSG.getTopicId(userId),
                ResultResponse.failure(
                    GameFruitErrorCode.GAME_FRUIT_TASK_AWARD_NOT_COMPLETED)));
        log.warn(
            "摩天轮游戏任务未满足,目标:" + quantity + ";quantity:" + awardConfig.getQuantity());
        return Boolean.TRUE;
      }

    }

    return Boolean.FALSE;

  }

  private Boolean checkReceive(GameFruitTaskAwardConfig awardConfig, Long userId) {

    Integer receiveDate = getReceiveDate(awardConfig);

    GameFruitUserTaskReceive taskReceive = gameFruitUserTaskReceiveService.checkReceive(
        awardConfig.getId(),
        userId, receiveDate);

    if (Objects.nonNull(taskReceive)) {
      messageSender.sendTopic(
          TopicMessage.of(
              MessageTypeTopic.GAME_FRUIT_RECEIVE_TASK_AWARD_MSG.getTopicId(userId),
              ResultResponse.failure(
                  GameFruitErrorCode.GAME_FRUIT_TASK_AWARD_IS_RECEIVED)));
      log.warn("摩天轮游戏任务已领取过！");
      return Boolean.TRUE;
    }

    return Boolean.FALSE;

  }

  private Integer getReceiveDate(GameFruitTaskAwardConfig awardConfig) {

    Integer receiveDate = LocalDateUtils.nowWeekMondayToInteger();

    if (Objects.equals(awardConfig.getTaskType(),
        GameFruitTaskEnum.WINNING_ONE_OF_THE_PRIZES_ONE.name()) ||
        Objects.equals(awardConfig.getTaskType(),
            GameFruitTaskEnum.WINNING_ONE_OF_THE_PRIZES_TWO.name()) ||
        Objects.equals(awardConfig.getTaskType(), GameFruitTaskEnum.NUMBER_OF_WINNING_ROUNDS.name())
        ||
        Objects.equals(awardConfig.getTaskType(), GameFruitTaskEnum.TASK_COMPLETE_DAY.name())
    ) {
      receiveDate = LocalDateUtils.nowToInteger();

    }

    return receiveDate;

  }
}
