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

import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
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.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 InviteUserRegisterService inviteUserRegisterService;
  private final InviteUserRechargeCommissionService inviteUserRechargeCommissionService;

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

    //根据被邀请人获得邀请人
    InviteUserRegister userRegister = getByInviteUserId(inviteUserId);
    if (Objects.isNull(userRegister)) {
      log.info("被邀请人获得邀请人 => null, inviteUserId:{}", inviteUserId);
      return;
    }

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

    //获得佣金比例
    Double commissionRate = getCommissionRate(sysOrigin);
    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(userRegister.getUserId(), commission);
    inviteUserRegisterService.incrCommission(userRegister.getInviteUserId(), commission);
    inviteUserRechargeCommissionService.add(sysOrigin,
        userRegister.getUserId(), userRegister.getInviteUserId(), commission);

    awardCommission(sysOrigin, userRegister.getUserId(), commission,
        userRegister.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());
    // TODO 2023-05-08 刘占洋， 有用户薅羊毛去除
//    walletRepository.changeGoldBalance(GoldReceipt.builder()
//        .consumeId(IdWorkerUtils.getId())
//        .trackId(inviteUserId)
//        .type(ReceiptType.INCOME)
//        .userId(userId)
//        .sysOrigin(SysOriginPlatformEnum.valueOf(sysOrigin))
//        .origin(GoldOrigin.INVITE_USER_REWARDS)
//        .amount(amount)
//        .build());
  }

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

  private Double getCommissionRate(String sysOrigin) {
    return userInviteCacheService
        .getCommissionRate(SysOriginPlatformEnum.valueOf(sysOrigin));
  }

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

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

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

}
