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


import com.red.circle.component.mq.MessageEventProcess;
import com.red.circle.component.mq.MessageEventProcessDescribe;
import com.red.circle.component.mq.config.RocketMqMessageListener;
import com.red.circle.component.mq.service.Action;
import com.red.circle.component.mq.service.ConsumerMessage;
import com.red.circle.component.mq.service.MessageListener;
import com.red.circle.mq.business.model.event.gift.GameLuckyGiftBusinessEvent;
import com.red.circle.mq.rocket.business.streams.GameLuckyGiftBusinessSink;
import com.red.circle.other.app.common.gift.GameLuckyGiftCommon;
import com.red.circle.other.app.common.gift.LuckyGiftGoClient;
import com.red.circle.other.app.common.gift.LuckyGiftResultProcessor;
import com.red.circle.other.app.common.gift.GameLuckyGiftParamCmd;
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
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.tool.core.text.StringUtils;
import com.red.circle.tool.core.date.LocalDateTimeUtils;
import java.util.stream.Collectors;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 游戏幸运礼物抽奖.
 *
 * @author pengshigang on 2023/7/28
 */
@Slf4j
@RocketMqMessageListener(groupId = GameLuckyGiftBusinessSink.INPUT, tag = GameLuckyGiftBusinessSink.TAG)
@RequiredArgsConstructor
public class GameLuckyGiftBusinessListener implements MessageListener {

  private final UserRegionGateway userRegionGateway;
  private final MessageEventProcess messageEventProcess;
  private final GameLuckyGiftCommon gameLuckyGiftManager;
  private final RoomProfileManagerService roomProfileManagerService;
  private final LuckyGiftGoClient luckyGiftGoClient;
  private final LuckyGiftResultProcessor luckyGiftResultProcessor;

  @Override
  public Action consume(ConsumerMessage message) {

    return messageEventProcess.consume(
        MessageEventProcessDescribe.builder()
            .logTag("游戏幸运礼物抽奖")
            .consumeMsgTimeoutMinute(60 * 3)
            .repeatConsumeMinute(30)
            .repeatConsumeTag("GameLuckyGiftBusiness")
            .checkConsumeTag(GameLuckyGiftBusinessSink.TAG)
            .message(message)
            .build(),
        GameLuckyGiftBusinessEvent.class,
        this::processLottery);
  }

  /**
   * 保存幸运礼物流水.
   */
  private void processLottery(GameLuckyGiftBusinessEvent event) {
    processLotteryEvent(event);
  }

  public LuckyGiftGoClient.LuckyGiftGoDrawResponse processLotteryEvent(GameLuckyGiftBusinessEvent event) {
    if (Objects.isNull(event.getRoomId())) {
      log.warn("Lucky gift event missing roomId, businessId={}", event.getBusinessId());
      return null;
    }

    long startTime = LocalDateTimeUtils.nowEpochMilli();

    try {
      RoomProfile roomProfile = roomProfileManagerService.getProfileById(event.getRoomId());
      if (Objects.nonNull(roomProfile)) {
        event.setRoomAccount(roomProfile.getRoomAccount());
      } else if (StringUtils.isBlank(event.getBusinessId())) {
        log.warn("Lucky gift room profile missing for legacy flow, roomId={}", event.getRoomId());
        return null;
      } else {
        log.warn("Lucky gift room profile missing, continue go draw with fallback roomAccount, businessId={}, roomId={}",
            event.getBusinessId(), event.getRoomId());
      }

      if (StringUtils.isBlank(event.getRegionCode())) {
        event.setRegionCode(userRegionGateway.getRegionCode(event.getUserId()));
      }

      if (StringUtils.isBlank(event.getBusinessId())) {
        GameLuckyGiftParamCmd cmd = buildLuckyGiftRunParam(event, roomProfile);
        event.getUsers().forEach(user -> {
          cmd.setId(user.getId());
          cmd.setGiftsCount(user.getGiftsCount());
          cmd.setAcceptUserId(user.getAcceptUserId());
          cmd.setComboLossCount(user.getComboLossCount());
          gameLuckyGiftManager.run(cmd);
        });
        return null;
      }

      LuckyGiftGoClient.LuckyGiftGoDrawResponse response = drawWithGo(event);
      luckyGiftResultProcessor.process(event, response);
      return response;
    } finally {
      long endTime = LocalDateTimeUtils.nowEpochMilli() - startTime;
      if (endTime > (1000 * 20)) {
        log.warn("[游戏幸运礼物抽奖] 队列处理耗时:{}", endTime);
      }
    }
  }

  public LuckyGiftGoClient.LuckyGiftGoDrawResponse drawWithGo(GameLuckyGiftBusinessEvent event) {
    LuckyGiftGoClient.LuckyGiftGoDrawResponse response = luckyGiftGoClient.draw(buildGoRequest(event));
    if (!Objects.equals(event.getBusinessId(), response.getBusinessId())) {
      throw new IllegalStateException("Lucky gift businessId mismatch, request=" + event.getBusinessId()
          + ", response=" + response.getBusinessId());
    }
    log.info("Lucky gift go draw success businessId={}, standardId={}, providerCode={}, rewardTotal={}",
        event.getBusinessId(), event.getStandardId(), response.getProviderCode(), response.getRewardTotal());
    return response;
  }

  private GameLuckyGiftParamCmd buildLuckyGiftRunParam(GameLuckyGiftBusinessEvent event,
      RoomProfile roomProfile) {
    return new GameLuckyGiftParamCmd()
        .setUserId(event.getUserId())
        .setRoomId(event.getRoomId())
        .setRoomAccount(roomProfile.getRoomAccount())
        .setSysOrigin(event.getSysOrigin())
        .setGiftId(event.getGiftId())
        .setQuantity(event.getQuantity())
        .setCheckCombo(event.getCheckCombo())
        .setGiftCombos(event.getGiftCombos())
        .setOpenComboLoss(event.getOpenComboLoss())
        .setSysComboLoss(event.getSysComboLoss())
        .setOpenGiftGiveTotal(event.getOpenGiftGiveTotal())
        .setSysGiftGiveTotal(event.getSysGiftGiveTotal())
        .setRegionCode(userRegionGateway.getRegionCode(event.getUserId()))
        .setStandardId(event.getStandardId());
  }

  private LuckyGiftGoClient.LuckyGiftGoDrawRequest buildGoRequest(GameLuckyGiftBusinessEvent event) {
    return new LuckyGiftGoClient.LuckyGiftGoDrawRequest()
        .setBusinessId(event.getBusinessId())
        .setConsumeAssetRecordId(event.getConsumeAssetRecordId())
        .setSysOrigin(event.getSysOrigin())
        .setStandardId(event.getStandardId())
        .setRoomId(event.getRoomId())
        .setSendUserId(event.getUserId())
        .setGiftId(event.getGiftId())
        .setGiftPrice(Objects.nonNull(event.getGiftPrice()) ? event.getGiftPrice().longValue() : 0L)
        .setGiftNum(Objects.nonNull(event.getQuantity()) ? Long.valueOf(event.getQuantity()) : 0L)
        .setGiftIsFree(Boolean.TRUE.equals(event.getGiftIsFree()))
        .setOrders(event.getUsers().stream().map(user ->
            new LuckyGiftGoClient.LuckyGiftGoDrawOrder()
                .setId(Objects.toString(user.getId(), null))
                .setAcceptUserId(user.getAcceptUserId())
        ).collect(Collectors.toList()));
  }


}
