package com.red.circle.other.app.common.gift;

import com.red.circle.component.redis.service.RedisService;
import com.red.circle.other.domain.enums.VipBenefitType;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
import com.red.circle.other.domain.model.user.ability.RegionConfig;
import com.red.circle.other.infra.common.team.TeamTargetCommon;
import com.red.circle.other.infra.database.mongo.entity.live.RoomProfile;
import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberService;
import com.red.circle.other.infra.database.rds.service.user.user.ConsumptionLevelService;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.num.ArithmeticUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 幸运礼物送出后的统计补偿.
 * 只补房间流水、魅力值、主播收礼积分，固定按 10% 结算。
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class LuckyGiftSendMetricsService {

  private static final String PROCESSED_KEY_PREFIX = "lucky_gift:send:metrics:processed:";
  private static final BigDecimal LUCKY_GIFT_METRIC_RATIO = new BigDecimal("0.1");

  private final RedisService redisService;
  private final TeamTargetCommon teamTargetCommon;
  private final TeamMemberService teamMemberService;
  private final UserRegionGateway userRegionGateway;
  private final UserProfileGateway userProfileGateway;
  private final ConsumptionLevelService consumptionLevelService;
  private final RoomProfileManagerService roomProfileManagerService;

  public void settle(
      String idempotencyKey,
      Long roomId,
      Long sendUserId,
      BigDecimal giftUnitPrice,
      Integer quantity,
      List<Long> acceptUserIds
  ) {
    if (StringUtils.isBlank(idempotencyKey) || sendUserId == null || giftUnitPrice == null
        || quantity == null || quantity <= 0 || CollectionUtils.isEmpty(acceptUserIds)) {
      return;
    }

    if (!redisService.setIfAbsent(PROCESSED_KEY_PREFIX + idempotencyKey, "1", 7,
        TimeUnit.DAYS)) {
      return;
    }

    BigDecimal singleGiftAmount = giftUnitPrice.multiply(BigDecimal.valueOf(quantity));
    BigDecimal singleMetricAmount = calculateMetricAmount(singleGiftAmount);
    if (ArithmeticUtils.lteZero(singleMetricAmount)) {
      return;
    }

    settleRoomValue(roomId, sendUserId, singleGiftAmount, acceptUserIds.size());
    settleCharm(acceptUserIds, singleMetricAmount);
    settleHostPoints(sendUserId, acceptUserIds, singleMetricAmount);
  }

  private void settleRoomValue(Long roomId, Long sendUserId, BigDecimal singleGiftAmount,
      int acceptSize) {
    if (roomId == null || acceptSize <= 0) {
      return;
    }

    RoomProfile roomProfile = roomProfileManagerService.getProfileById(roomId);
    if (roomProfile == null || !Objects.equals(roomProfile.getUserId(), sendUserId)
        || teamMemberService.getByMemberId(sendUserId) == null) {
      return;
    }

    BigDecimal roomMetricAmount = calculateMetricAmount(
        singleGiftAmount.multiply(BigDecimal.valueOf(acceptSize)));
    if (ArithmeticUtils.lteZero(roomMetricAmount)) {
      return;
    }
    teamTargetCommon.incrementRoomValue(sendUserId, roomMetricAmount);
  }

  private void settleCharm(List<Long> acceptUserIds, BigDecimal singleMetricAmount) {
    for (Long acceptUserId : acceptUserIds) {
      if (acceptUserId == null) {
        continue;
      }

      BigDecimal vipBenefit = Objects.requireNonNullElse(
          userProfileGateway.getUserVipBenefit(acceptUserId, VipBenefitType.XP_RATE),
          VipBenefitType.XP_RATE.getDefaultValue()
      );
      BigDecimal charmAmount = singleMetricAmount.multiply(vipBenefit)
          .setScale(0, RoundingMode.DOWN);
      if (ArithmeticUtils.lteZero(charmAmount)) {
        continue;
      }
      consumptionLevelService.incrConsumptionDiamond(acceptUserId, charmAmount);
    }
  }

  private void settleHostPoints(Long sendUserId, List<Long> acceptUserIds,
      BigDecimal singleMetricAmount) {
    RegionConfig sendRegion = userRegionGateway.getRegionConfigByUserId(sendUserId);
    if (sendRegion == null || StringUtils.isBlank(sendRegion.getRegionCode())) {
      return;
    }

    Set<Long> anchorUserIds = new HashSet<>(
        teamMemberService.listMemberIds(new HashSet<>(acceptUserIds)));
    for (Long acceptUserId : acceptUserIds) {
      if (acceptUserId == null || !anchorUserIds.contains(acceptUserId)) {
        continue;
      }

      RegionConfig acceptRegion = userRegionGateway.getRegionConfigByUserId(acceptUserId);
      if (acceptRegion == null || StringUtils.isBlank(acceptRegion.getRegionCode())) {
        continue;
      }

      if (!userRegionGateway.checkBusinessRegionCode(sendRegion.getRegionCode(),
          acceptRegion.getRegionCode())) {
        continue;
      }

      teamTargetCommon.incrementGiftValue(acceptUserId, singleMetricAmount);
    }
  }

  private BigDecimal calculateMetricAmount(BigDecimal amount) {
    if (ArithmeticUtils.lteZero(amount)) {
      return BigDecimal.ZERO;
    }
    return amount.multiply(LUCKY_GIFT_METRIC_RATIO).setScale(0, RoundingMode.DOWN);
  }
}
