package com.red.circle.other.app.command.user.query;

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.tool.core.sequence.IdWorkerUtils;
import com.red.circle.other.app.convertor.user.RedPacketInviteAppConvertor;
import com.red.circle.other.app.dto.clientobject.user.invite.InviteRedPacketUserCheckAuthCO;
import com.red.circle.other.app.dto.cmd.user.user.InviteUserRedPacketCmd;
import com.red.circle.other.infra.common.user.RedPacketInviteUserCommon;
import com.red.circle.other.infra.database.cache.service.user.RedPacketInviteUserCacheService;
import com.red.circle.other.infra.database.rds.entity.user.user.InviteRedPacketHelp;
import com.red.circle.other.infra.database.rds.entity.user.user.InviteRedPacketRecord;
import com.red.circle.other.infra.database.rds.entity.user.user.LatestMobileDevice;
import com.red.circle.other.infra.database.rds.service.user.device.LatestMobileDeviceService;
import com.red.circle.other.infra.database.rds.service.user.user.InviteRedPacketHelpService;
import com.red.circle.other.infra.database.rds.service.user.user.InviteRedPacketRecordService;
import com.red.circle.other.infra.database.rds.service.user.user.RecentlyActiveService;
import com.red.circle.other.infra.enums.user.user.InviteHelpUserTypeEnum;
import com.red.circle.other.infra.enums.user.user.InviteRedPacketSourceEnum;
import java.sql.Timestamp;
import java.util.Objects;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 开红包权限校验与帮砍一刀.
 * </p>
 *
 * @author pengshigang
 * @since 2023-12-20
 */
@Service
@AllArgsConstructor
public class InviteNewRedPacketAuthCheckQryExe {

  private final RedisService redisService;
  private final RecentlyActiveService recentlyActiveService;
  private final LatestMobileDeviceService latestMobileDeviceService;
  private final RedPacketInviteUserCommon redPacketInviteUserCommon;
  private final InviteRedPacketHelpService inviteRedPacketHelpService;
  private final RedPacketInviteAppConvertor redPacketInviteAppConvertor;
  private final InviteRedPacketRecordService inviteRedPacketRecordService;
  private final RedPacketInviteUserCacheService redPacketInviteUserCacheService;

  public InviteRedPacketUserCheckAuthCO execute(InviteUserRedPacketCmd cmd) {

    InviteRedPacketUserCheckAuthCO checkAuth = getUserCheckAuth(cmd);

    if (Boolean.TRUE.equals(checkAuth.getClosed())) {
      return checkAuth;
    }
    if (Boolean.FALSE.equals(checkAuth.getShowInviteRedPacket())) {
      return checkAuth;
    }
    if (Boolean.FALSE.equals(checkAuth.getInviteCodeEffective())) {
      return checkAuth;
    }

    if (Objects.isNull(checkAuth.getInviter()) ||
        !Objects.equals(InviteRedPacketSourceEnum.USER_INVITATION.name(), cmd.getSource())) {
      return checkAuth;
    }

    // 邀请人红包
    InviteRedPacketRecord invitePeopleRedPacket = getUserRedPacketByUndone(checkAuth);
    if (Objects.isNull(invitePeopleRedPacket)) {
      return checkAuth;
    }
    //查看是否为违规用户
    if(invitePeopleRedPacket.getViolationOrNot() != null &&invitePeopleRedPacket.getViolationOrNot().equals(Boolean.FALSE)){
      return checkAuth;
    }

    try {

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

      return processInviteHelp(cmd, checkAuth, invitePeopleRedPacket.getId());
    } finally {
      redisService.unlock(lockKey(cmd.getReqUserId()));
    }

  }

  /**
   * 助力次数增加.
   */
  private InviteRedPacketUserCheckAuthCO processInviteHelp(InviteUserRedPacketCmd cmd,
      InviteRedPacketUserCheckAuthCO checkAuth, Long invitePeopleRedPacketId) {

    LatestMobileDevice inviterDevice = getInviteMobileDevice(checkAuth.getInviter().getId());
    if (Objects.isNull(inviterDevice)) {
      return checkAuth;
    }

    String userType;
    Timestamp lastActiveTime = getLastActiveTime(cmd);
    if (Objects.isNull(lastActiveTime)) {
      // 新用户校验与助力
      checkAuth.setShowHelpTis(
          redPacketInviteUserCommon.checkNewUserAndHelp(cmd.getReqUserId(),
              checkAuth.getInviter().getId()));
      userType = InviteHelpUserTypeEnum.NEW_USER.name();
    } else {
      // 回归用户校验与助力
      checkAuth.setShowHelpTis(
          redPacketInviteUserCommon.checkReturnUserAndHelp(cmd.getReqUserId(),
              checkAuth.getInviter().getId(), lastActiveTime));
      userType = InviteHelpUserTypeEnum.RETURN_USER.name();
    }

    // 不能助力
    if (Boolean.FALSE.equals(checkAuth.getShowHelpTis())) {
      return checkAuth;
    }

    // 增加邀请人红包邀请人数
    inviteRedPacketRecordService.incrInviteMemberCount(invitePeopleRedPacketId);
    // 增加邀请人抽奖次数
    redPacketInviteUserCacheService.incrRedPacketLotteryCount(invitePeopleRedPacketId);

    saveRedPacketHelp(cmd, checkAuth, invitePeopleRedPacketId, userType, inviterDevice);
    return checkAuth;
  }

  private Timestamp getLastActiveTime(InviteUserRedPacketCmd cmd) {
    return recentlyActiveService.getLastActiveTime(cmd.getReqUserId());
  }

  private InviteRedPacketUserCheckAuthCO getUserCheckAuth(InviteUserRedPacketCmd cmd) {
    return redPacketInviteAppConvertor.toInviteUserCheckAuthCO(redPacketInviteUserCommon.
        getUserCheckAuth(cmd.getReqUserId(), cmd.getInviteCode()));
  }

  /**
   * 保存红包助力记录.
   */
  private void saveRedPacketHelp(InviteUserRedPacketCmd cmd,
      InviteRedPacketUserCheckAuthCO checkAuth, Long invitePeopleRedPacketId,
      String userType, LatestMobileDevice inviterDevice) {

    InviteRedPacketHelp redPacketHelp = new InviteRedPacketHelp();

    redPacketHelp.setId(IdWorkerUtils.getId());
    redPacketHelp.setSysOrigin(cmd.getReqSysOrigin().getOrigin());
    redPacketHelp.setRedPacketId(invitePeopleRedPacketId);
    redPacketHelp.setUserId(cmd.getReqUserId());
    redPacketHelp.setIp(checkAuth.getIp());
    redPacketHelp.setImei(checkAuth.getImei());
    redPacketHelp.setInviteUserId(inviterDevice.getUserId());
    redPacketHelp.setInviteIp(inviterDevice.getIp());
    redPacketHelp.setInviteImei(inviterDevice.getImei());
    redPacketHelp.setUserType(userType);

    inviteRedPacketHelpService.save(redPacketHelp);
  }

  private LatestMobileDevice getInviteMobileDevice(Long userId) {
    return latestMobileDeviceService.getByUserId(userId);
  }

  private InviteRedPacketRecord getUserRedPacketByUndone(InviteRedPacketUserCheckAuthCO checkAuth) {
    return inviteRedPacketRecordService.getUserRedPacketByUndone(checkAuth.getInviter().getId());
  }

  private String lockKey(Long userId) {
    return "GAME_INVITE_NEW_HELP:".concat(userId.toString());
  }

}
