package com.red.circle.other.app.listener.gift.strategy;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import com.red.circle.mq.business.model.event.gift.OfflineProcessGiftEvent;
import com.red.circle.other.app.common.gift.GameLuckyGiftCommon;
import com.red.circle.other.app.service.activity.RankingActivityService;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
import com.red.circle.other.infra.common.game.GameKtvCommon;
import com.red.circle.other.infra.database.cache.service.cp.CpRelationshipCacheService;
import com.red.circle.other.infra.database.cache.service.other.ActivityConfigCacheService;
import com.red.circle.other.infra.database.cache.service.user.UserCpValueCacheService;
import com.red.circle.other.infra.database.mongo.entity.gift.GiftAcceptUser;
import com.red.circle.other.infra.database.mongo.entity.gift.GiftGiveRunningWater;
import com.red.circle.other.infra.database.mongo.entity.gift.GiftValue;
import com.red.circle.other.infra.database.mongo.service.activity.AppRankCountService;
import com.red.circle.other.infra.database.mongo.service.activity.TemporaryActivityCountService;
import com.red.circle.other.infra.database.mongo.service.activity.WeekKingQueenCountService;
import com.red.circle.other.infra.database.mongo.service.activity.WeekStarGiftCountService;
import com.red.circle.other.infra.database.mongo.service.gift.GiftGiveRunningWaterService;
import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManagerService;
import com.red.circle.other.infra.database.mongo.service.sys.SysActivityCountService;
import com.red.circle.other.infra.database.mongo.service.user.count.WeekCpValueCountService;
import com.red.circle.other.infra.database.rds.entity.user.user.CpRelationship;
import com.red.circle.other.infra.database.rds.service.user.user.CpRelationshipService;
import com.red.circle.other.infra.database.rds.service.user.user.CpValueService;
import com.red.circle.other.infra.enums.user.user.CpRelationshipType;
import com.red.circle.other.inner.enums.material.GiftCurrencyType;
import java.math.BigDecimal;
import java.util.List;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;

class RankCountStrategyTest {

  private final CpValueService cpValueService = mock(CpValueService.class);
  private final UserProfileGateway userProfileGateway = mock(UserProfileGateway.class);
  private final AppRankCountService appRankCountService = mock(AppRankCountService.class);
  private final CpRelationshipService cpRelationshipService = mock(CpRelationshipService.class);
  private final UserCpValueCacheService userCpValueCacheService = mock(
      UserCpValueCacheService.class);
  private final WeekCpValueCountService weekCpValueCountService = mock(
      WeekCpValueCountService.class);
  private final GiftGiveRunningWaterService giftGiveRunningWaterService = mock(
      GiftGiveRunningWaterService.class);
  private final CpRelationshipCacheService cpRelationshipCacheService = mock(
      CpRelationshipCacheService.class);
  private final ActivityConfigCacheService activityConfigCacheService = mock(
      ActivityConfigCacheService.class);

  private final RankCountStrategy strategy = new RankCountStrategy(
      mock(GameKtvCommon.class),
      cpValueService,
      userProfileGateway,
      mock(UserRegionGateway.class),
      appRankCountService,
      mock(GameLuckyGiftCommon.class),
      cpRelationshipService,
      userCpValueCacheService,
      weekCpValueCountService,
      mock(SysActivityCountService.class),
      mock(WeekStarGiftCountService.class),
      mock(RoomProfileManagerService.class),
      mock(WeekKingQueenCountService.class),
      giftGiveRunningWaterService,
      mock(TemporaryActivityCountService.class),
      mock(RankingActivityService.class),
      cpRelationshipCacheService,
      activityConfigCacheService);

  @ParameterizedTest
  @EnumSource(CpRelationshipType.class)
  void processorShouldIncreaseRelationValueForNormalGoldGift(CpRelationshipType relationType) {
    GiftGiveRunningWater runningWater = runningWater("NORMAL");
    CpRelationship relationship = new CpRelationship()
        .setCpValId(3003L)
        .setUserId(1001L)
        .setCpUserId(2002L)
        .setRelationType(relationType.name());

    when(giftGiveRunningWaterService.getByIdPrimary(9009L)).thenReturn(runningWater);
    when(cpRelationshipService.getByUserId(1001L, (String) null))
        .thenReturn(List.of(relationship));
    when(activityConfigCacheService.listOngoing("LIKEI")).thenReturn(List.of());

    strategy.processor(new OfflineProcessGiftEvent().setRunningWaterId(9009L));

    verify(cpRelationshipService).getByUserId(1001L, (String) null);
    verify(cpValueService).incrValue(3003L, new BigDecimal("25"));
    verify(userCpValueCacheService).incr(1001L, 2002L, 25L);
    verify(cpRelationshipCacheService).remove(List.of(1001L, 2002L));
    verify(weekCpValueCountService).incrThisWeekQuantity("LIKEI", 1001L, 2002L, 25L);
    verify(weekCpValueCountService).incrThisSeasonQuantity("LIKEI", 1001L, 2002L, 25L);
  }

  private GiftGiveRunningWater runningWater(String giftType) {
    return new GiftGiveRunningWater()
        .setId(9009L)
        .setSysOrigin("LIKEI")
        .setOriginId("chat")
        .setUserId(1001L)
        .setGiftId(5005L)
        .setGiftValue(new GiftValue()
            .setCurrencyType(GiftCurrencyType.GOLD.name())
            .setGiftType(giftType)
            .setGiftValue(new BigDecimal("25"))
            .setActualAmount(new BigDecimal("25")))
        .setAcceptUsers(List.of(new GiftAcceptUser()
            .setAcceptUserId(2002L)));
  }
}
