package com.red.circle.other.infra.gateway.user;

import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.domain.model.user.UserProfile;
import com.red.circle.other.infra.database.rds.dao.user.user.UserInviteUserDAO;
import com.red.circle.other.infra.database.rds.entity.user.user.InviteUserRechargeCommission;
import com.red.circle.other.infra.database.rds.entity.user.user.OneTimeTask;
import com.red.circle.other.infra.database.rds.entity.user.user.UserInviteUser;
import com.red.circle.other.infra.database.rds.service.user.user.OneTimeTaskService;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.other.domain.gateway.user.ability.InviteUserGateway;
import com.red.circle.other.infra.database.cache.service.user.UserInviteCacheService;
import com.red.circle.other.infra.database.rds.entity.user.user.InviteUserRegister;
import com.red.circle.other.infra.database.rds.service.user.user.InviteUserRechargeCommissionService;
import com.red.circle.other.infra.database.rds.service.user.user.InviteUserRegisterService;
import com.red.circle.other.infra.database.rds.service.user.user.InviteUserSummaryService;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 被邀请的用户充值，邀请人获得佣金处理 实现.
 *
 * @author pengliang on 2023/12/17
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class InviteUserGatewayImpl implements InviteUserGateway {

  private final WalletGoldClient walletGoldClient;
  private final UserInviteCacheService userInviteCacheService;
  private final InviteUserSummaryService inviteUserSummaryService;
  private final UserInviteUserDAO userInviteUserDAO;
  private final UserProfileGateway userProfileGateway;
  private final InviteUserRechargeCommissionService inviteUserRechargeCommissionService;
  private final OneTimeTaskService oneTimeTaskService;

  /**
   * 被邀请人充值邀请人获得佣金
   *
   * @param rechargeAmount 充值金额
   * @param sysOrigin      系统
   * @param inviteUserId   被邀请人(充值人)
   */
  @Override
  public void getRechargeCommission(BigDecimal rechargeAmount, String sysOrigin,
      Long inviteUserId) {

    //根据被邀请人获得邀请人
    UserInviteUser userInviteUser = getByInviteUserId(inviteUserId);
    if (Objects.isNull(userInviteUser)) {
      return;
    }

    //能够赚取佣金的天数
    Integer commissionDays = getCommissionDays(sysOrigin);
    if (Objects.isNull(commissionDays)) {
      log.info("能够赚取佣金的天数 => null, inviteUserId:{}", inviteUserId);
      return;
    }
    //邀请时间 + 有效天数 > 当前时间 则可以继续获得佣金。
    Timestamp limitedTime = getLimitedTime(userInviteUser, commissionDays);
    if (limitedTime.compareTo(TimestampUtils.now()) < 0) {
      log.info("邀请时间 + 有效天数 < 当前时间, inviteUserId:{}", inviteUserId);
      return;
    }

    //获得佣金比例
    Double commissionRate = getCommissionRate(sysOrigin, userInviteUser.getInviteUserId());
    if (Objects.isNull(commissionRate)) {
      log.info("获得佣金比例 => null, inviteUserId:{}", inviteUserId);
      return;
    }

    //获得的佣金 = 糖果数 * 佣金比例
    BigDecimal commission = getCommission(rechargeAmount, commissionRate);
    if (commission.compareTo(BigDecimal.ZERO) <= 0) {
      log.info("糖果数 * 佣金比例 <= 0, inviteUserId:{}", inviteUserId);
      return;
    }

    inviteUserSummaryService.incrCommission(userInviteUser.getUserId(), commission);
    inviteUserRechargeCommissionService.add(sysOrigin, userInviteUser.getUserId(), userInviteUser.getInviteUserId(), commission);

    // 累计邀请人数：判断inviteUserRechargeCommissionService里是否已有该被邀请人的记录
    // 查询该被邀请人在此之前是否有充值记录
    long recordCount = inviteUserRechargeCommissionService.query()
        .eq(InviteUserRechargeCommission::getUserId, userInviteUser.getUserId())
        .eq(InviteUserRechargeCommission::getInviteUserId, userInviteUser.getInviteUserId())
        .count();

    // 如果记录数 < 1，说明是首次充值（当前这条刚插入），才累计邀请人数+1
    if (recordCount < 1) {
      log.info("被邀请人首次充值，累计邀请人数+1, inviterUserId:{}, inviteUserId:{}",
          userInviteUser.getUserId(), userInviteUser.getInviteUserId());
      inviteUserSummaryService.incrUser(userInviteUser.getUserId(), 1);
    }

    awardCommission(sysOrigin, userInviteUser.getUserId(), commission, userInviteUser.getInviteUserId());
  }

  /**
   * 奖励佣金
   *
   * @param sysOrigin    系统
   * @param userId       邀请人(获得佣金的人)
   * @param amount       佣金
   * @param inviteUserId 被邀请人(充值人)
   */
  private void awardCommission(String sysOrigin, Long userId, BigDecimal amount, Long inviteUserId) {
    walletGoldClient.changeBalance(GoldReceiptCmd.builder()
            .appIncome()
            .userId(userId)
            .eventId(inviteUserId)
            .sysOrigin(sysOrigin)
            .origin(GoldOrigin.INVITE_USER_REWARDS)
            .originDescribe(GoldOrigin.INVITE_USER_REWARDS.getDesc())
            .amount(amount)
            .closeDelayAsset()
            .build());
  }

  private BigDecimal getCommission(BigDecimal rechargeAmount, Double commissionRate) {
    return rechargeAmount.multiply(BigDecimal.valueOf(commissionRate))
        .setScale(0, RoundingMode.DOWN);
  }

  private Double getCommissionRate(String sysOrigin, Long userId) {
      Double commissionRate = userInviteCacheService.getCommissionRate(SysOriginPlatformEnum.valueOf(sysOrigin));

      UserProfile userProfile = userProfileGateway.getByUserId(userId);
      Duration duration = Duration.between(userProfile.getCreateTime().toLocalDateTime(), LocalDateTime.now());
      if (duration.toDays() < 7) {
          OneTimeTask oneTimeTask = oneTimeTaskService.queryCompletedFirstCharge(userId, sysOrigin);
          if (Objects.isNull(oneTimeTask)) {
              commissionRate += 0.03;
          }
      }
    return commissionRate;
  }

  private UserInviteUser getByInviteUserId(Long inviteUserId) {
    if (Objects.isNull(inviteUserId)) {
      return null;
    }

    List<UserInviteUser> allInvites = userInviteUserDAO.selectList(
        new LambdaQueryWrapper<UserInviteUser>()
            .eq(UserInviteUser::getInviteUserId, inviteUserId)
            .orderByDesc(UserInviteUser::getCreateTime)
    );
    if (CollectionUtils.isEmpty(allInvites)) {
      return null;
    }

    return allInvites.get(0);
  }

  private Integer getCommissionDays(String sysOrigin) {
    return userInviteCacheService
        .getCommissionDays(SysOriginPlatformEnum.valueOf(sysOrigin));
  }

  private Timestamp getLimitedTime(UserInviteUser userInviteUser, Integer commissionDays) {
    return TimestampUtils
        .dateTimestampPlusDays(userInviteUser.getCreateTime().toLocalDateTime(), commissionDays);
  }

}
