package com.red.circle.other.app.command.activity.query;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import com.red.circle.common.business.enums.PropsActivityRewardEnum;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.other.app.dto.clientobject.sys.ActivityConfigRewardsCO;
import com.red.circle.other.app.dto.clientobject.sys.ActivityConfigVO;
import com.red.circle.other.inner.endpoint.material.gift.GiftConfigClient;
import com.red.circle.other.inner.endpoint.material.props.BadgeSourceClient;
import com.red.circle.other.inner.endpoint.material.props.PropsActivityRewardConfigClient;
import com.red.circle.other.inner.endpoint.sys.SysActivityConfigClient;
import com.red.circle.other.inner.model.cmd.material.BadgePictureMapQry;
import com.red.circle.other.inner.model.cmd.sys.ActivityConfigBackQryCmd;
import com.red.circle.other.inner.model.dto.material.BadgePictureConfigDTO;
import com.red.circle.other.inner.model.dto.material.GiftConfigDTO;
import com.red.circle.other.inner.model.dto.material.PropsActivityRewardConfigInfoDTO;
import com.red.circle.other.inner.model.dto.sys.ActivityConfigDTO;
import com.red.circle.other.inner.model.dto.sys.ActivityConfigRewardsDTO;
import com.red.circle.other.inner.model.dto.sys.ActivityTemplateValueDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.text.StringUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@RequiredArgsConstructor
public class WeekKingQueenActivityExe {
  private final SysActivityConfigClient sysActivityConfigClient;
  private final GiftConfigClient giftConfigClient;
  private final BadgeSourceClient badgeSourceClient;
  private final PropsActivityRewardConfigClient propsActivityRewardConfigClient;

  public ActivityConfigVO getEffectiveActivity(AppExtCommand cmd, String templateId) {
    ActivityConfigBackQryCmd query = new ActivityConfigBackQryCmd();
    query.setSysOrigin(cmd.getReqSysOrigin().getOrigin());
    if (StringUtils.isNotBlank(templateId)) {
      query.setTemplateId(Long.parseLong(templateId));
    }

    ActivityConfigDTO activityConfigDTO = ResponseAssert.requiredSuccess(sysActivityConfigClient.effectiveActivityByTemplate(query.getTemplateId(), ""));

    if (activityConfigDTO == null) {
      return null;
    }

    List<ActivityConfigDTO> activityConfigs = List.of(activityConfigDTO);
    Map<Long, ActivityTemplateValueDTO> templateValueMap = ResponseAssert.requiredSuccess(
        sysActivityConfigClient.mapByIds(
            activityConfigs.stream().map(ActivityConfigDTO::getTemplateId).collect(
                Collectors.toSet())));

    Map<Long, List<PropsActivityRewardConfigInfoDTO>> rewardMaps = this.mapSourceGroup(
        cmd.getReqSysOrigin().getOrigin(), getRewardGroupIds(activityConfigs));

    Map<Long, GiftConfigDTO> sysGiftConfigMap = ResponseAssert.requiredSuccess(
        giftConfigClient.mapByIds(
            activityConfigs.stream()
                .map(ActivityConfigDTO::getGiftIds)
                .filter(CollectionUtils::isNotEmpty)
                .flatMap(Collection::stream)
                .filter(Objects::nonNull)
                .map(Long::parseLong)
                .collect(Collectors.toSet())));

    return activityConfigs.stream().map(conf ->
        new ActivityConfigVO()
            .setConfig(conf)
            .setButOneRewards(getRewards(rewardMaps, conf.getButOneRewards()))
            .setButTwoRewards(getRewards(rewardMaps, conf.getButTwoRewards()))
            .setTemplateName(Optional.ofNullable(templateValueMap.get(conf.getTemplateId()))
                .map(ActivityTemplateValueDTO::getName)
                .orElse(""))
            .setGifts(Optional.ofNullable(conf.getGiftIds())
                .map(giftIds -> giftIds.stream()
                    .map(giftId -> sysGiftConfigMap.get(Long.parseLong(giftId)))
                    .collect(Collectors.toList()))
                .orElseGet(Lists::newArrayList))
            .setStatus(conf.status())
            .setCountDown(conf.countDown())
    ).toList().get(0);
  }

  public Map<Long, List<PropsActivityRewardConfigInfoDTO>> mapSourceGroup(String sysOrigin,
                                                                          Set<Long> sourceGroupIds) {
    if (StringUtils.isBlank(sysOrigin) || CollectionUtils.isEmpty(sourceGroupIds)) {
      return Maps.newHashMap();
    }
    Map<Long, List<PropsActivityRewardConfigInfoDTO>> propsActivityRewardMap = ResponseAssert.requiredSuccess(
        propsActivityRewardConfigClient
            .mapByGroupIds(sourceGroupIds));
    Map<Long, BadgePictureConfigDTO> badgePictureMap = ResponseAssert.requiredSuccess(
        badgeSourceClient
            .mapPictureByIds(
                new BadgePictureMapQry()
                    .setBadgeIds(getBadgeIds(propsActivityRewardMap))
                    .setSysOrigin(sysOrigin)
            )
    );
    propsActivityRewardMap.values().stream().flatMap(Collection::stream)
        .filter(props -> Objects.equals(props.getType(),PropsActivityRewardEnum.BADGE.name()) || Objects.equals(props.getType(),PropsActivityRewardEnum.PROP_COUPON.name()))
        .forEach(props -> {
          BadgePictureConfigDTO picture = badgePictureMap.get(Long.valueOf(props.getContent()));
          if (Objects.isNull(picture)) {
            return;
          }
          props.setCover(picture.getSelectUrl());
          props.setSourceUrl(picture.getAnimationUrl());
        });
    return propsActivityRewardMap;
  }

  private Set<Long> getBadgeIds(
      Map<Long, List<PropsActivityRewardConfigInfoDTO>> propsActivityRewardMap) {
    return propsActivityRewardMap.values().stream().flatMap(Collection::stream)
        .filter(props -> Objects.equals(props.getType(),PropsActivityRewardEnum.BADGE.name()) || Objects.equals(props.getType(),PropsActivityRewardEnum.PROP_COUPON.name()))
        .map(props -> Long.valueOf(props.getContent()))
        .collect(Collectors.toSet());
  }

  private List<ActivityConfigRewardsCO> getRewards(
      Map<Long, List<PropsActivityRewardConfigInfoDTO>> rewardMaps,
      List<ActivityConfigRewardsDTO> rewardGroup) {
    return Optional.ofNullable(rewardGroup)
        .map(rewards -> rewards.stream().map(reward -> new ActivityConfigRewardsCO()
            .setRankRange(reward.getRankRange())
            .setResourceGroupId(reward.getResourceGroupId())
            .setRewards(rewardMaps.get(reward.getResourceGroupId()))
        ).collect(Collectors.toList()))
        .orElseGet(Lists::newArrayList);
  }


  private Set<Long> getRewardGroupIds(List<ActivityConfigDTO> activityConfigs) {
    return Stream.of(activityConfigs.stream().map(ActivityConfigDTO::getButOneRewards)
                .filter(CollectionUtils::isNotEmpty)
                .flatMap(Collection::stream)
                .map(ActivityConfigRewardsDTO::getResourceGroupId)
                .collect(Collectors.toSet()),
            activityConfigs.stream().map(ActivityConfigDTO::getButTwoRewards)
                .filter(CollectionUtils::isNotEmpty)
                .flatMap(Collection::stream)
                .map(ActivityConfigRewardsDTO::getResourceGroupId)
                .collect(Collectors.toSet()))
        .flatMap(Collection::stream)
        .collect(Collectors.toSet());
  }

}
