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

import com.google.common.collect.Lists;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.order.inner.endpoint.ProductClient;
import com.red.circle.order.inner.model.cmd.ProductConfigCmd;
import com.red.circle.order.inner.model.dto.ProductConfigDTO;
import com.red.circle.order.inner.model.dto.ProductConfigPackageDTO;
import com.red.circle.other.app.dto.clientobject.activity.FirstChargeIdCO;
import com.red.circle.other.app.dto.clientobject.activity.FirstChargeRewardPoolCO;
import com.red.circle.other.infra.database.rds.entity.activity.PropsActivityRewardConfig;
import com.red.circle.other.infra.database.rds.entity.activity.PropsActivityRuleConfig;
import com.red.circle.other.infra.database.rds.entity.badge.BadgePictureConfig;
import com.red.circle.other.infra.database.rds.entity.gift.GiftConfig;
import com.red.circle.other.infra.database.rds.entity.props.PropsSourceRecord;
import com.red.circle.other.infra.database.rds.service.activity.PropsActivityRewardConfigService;
import com.red.circle.other.infra.database.rds.service.activity.PropsActivityRuleConfigService;
import com.red.circle.other.infra.database.rds.service.badge.BadgePictureConfigService;
import com.red.circle.other.infra.database.rds.service.gift.GiftConfigService;
import com.red.circle.other.infra.database.rds.service.props.PropsSourceRecordService;
import com.red.circle.other.inner.enums.activity.PropsActivityTypeEnum;
import com.red.circle.other.inner.enums.material.PropsTypeEnum;
import com.red.circle.other.inner.model.dto.activity.props.ActivityRewardProps;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.json.JacksonUtils;
import com.red.circle.tool.core.num.ArithmeticUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

/**
 * 首充奖励池.
 *
 * @author pengshigang on 2021/8/3
 */
@Component
@RequiredArgsConstructor
public class FirstChargeRewardCmdExe {

  private final ProductClient productClient;
  private final GiftConfigService giftConfigService;
  private final PropsSourceRecordService propsSourceRecordService;
  private final BadgePictureConfigService badgePictureConfigService;
  private final PropsActivityRuleConfigService propsActivityRuleConfigService;
  private final PropsActivityRewardConfigService propsActivityRewardConfigService;

  public List<FirstChargeRewardPoolCO> execute(AppExtCommand cmd) {

    List<PropsActivityRuleConfig> ruleConfigs = listRuleConfigs(cmd);
    if (CollectionUtils.isEmpty(ruleConfigs)) {
      return Lists.newArrayList();
    }
    Map<Long, List<PropsActivityRewardConfig>> mapRewards = mapRewardsByGroupIds(ruleConfigs);

    Map<String, ProductConfigDTO> mapProduct = getMapProduct(cmd, ruleConfigs);

    Map<Long, List<ProductConfigPackageDTO>> packageMap = ResponseAssert.requiredSuccess(
        productClient.mapByProductCnfId(
            mapProduct.values().stream().map(ProductConfigDTO::getId).collect(Collectors.toSet())));

    return ruleConfigs.stream().map(rule -> {

      List<PropsActivityRewardConfig> rewards = mapRewards.get(rule.getResourceGroupId());
      if (CollectionUtils.isEmpty(rewards)) {
        return null;
      }

      ProductConfigDTO productConfig = mapProduct.get(getProductId(rule.getJsonData()));
      if (Objects.isNull(productConfig)) {
        return null;
      }

      List<ProductConfigPackageDTO> productConfigPackages = packageMap.get(productConfig.getId());
      if (CollectionUtils.isEmpty(productConfigPackages)) {
        return null;
      }

      return productConfigPackages.stream().filter(
              packageCnf -> Objects.equals(packageCnf.getPayPlatform(),
                  cmd.reqPlatformChannelEnum().name())
          ).findFirst()
          .map(packageCnf -> new FirstChargeRewardPoolCO()
              .setId(rule.getId())
              .setProductId(productConfig.getProductId())
              .setRechargeAmount(getAmount(productConfig))
              .setProductPackage(packageCnf.getProductPackage())
              .setActivityRewardProps(getActivityRewardPropsList(cmd, rewards))
          )
          .orElse(null);
    }).filter(Objects::nonNull).collect(Collectors.toList());

  }

  private String getAmount(ProductConfigDTO productConfig) {
    return "$" + productConfig.getUnitPrice().doubleValue();
  }

  private Map<String, ProductConfigDTO> getMapProduct(AppExtCommand cmd,
      List<PropsActivityRuleConfig> ruleConfigs) {

    return ResponseAssert.requiredSuccess(productClient
        .mapByProductIds(new ProductConfigCmd()
            .setProductIds(getProductCodeIds(ruleConfigs))
            .setIsAndroid(cmd.checkAndroid())
            .setSysOrigin(cmd.getReqSysOrigin().getOrigin())
        )
    );
  }


  private Set<String> getProductCodeIds(List<PropsActivityRuleConfig> ruleConfigs) {

    return ruleConfigs.stream().map(rule -> getProductId(rule.getJsonData()))
        .filter(StringUtils::isNotBlank).collect(Collectors.toSet());
  }

  private String getProductId(String jsonStr) {
    if (StringUtils.isBlank(jsonStr)) {
      return null;
    }
    FirstChargeIdCO firstChargeIdCO = JacksonUtils.readValue(jsonStr, FirstChargeIdCO.class);
    if (Objects.isNull(firstChargeIdCO) || StringUtils.isBlank(firstChargeIdCO.getProductId())) {
      return null;
    }
    return firstChargeIdCO.getProductId();
  }

  private List<ActivityRewardProps> getActivityRewardPropsList(AppExtCommand cmd,
      List<PropsActivityRewardConfig> rewards) {

    return rewards.stream()
        .map(reward -> getActivityRewardPropsCO(cmd, reward, getRewardBuild(reward)))
        .filter(Objects::nonNull).collect(Collectors.toList());
  }

  private ActivityRewardProps getActivityRewardPropsCO(AppExtCommand cmd,
      PropsActivityRewardConfig reward, ActivityRewardProps rewardPropsCO) {

    if (Objects.equals(reward.getType(), PropsTypeEnum.GOLD.name()) ||
        Objects.equals(reward.getType(), PropsTypeEnum.DIAMOND.name())) {
      rewardPropsCO.setAmount(ArithmeticUtils.toBigDecimal(reward.getContent()));
      return rewardPropsCO;
    }

    if (Objects.equals(reward.getType(), PropsTypeEnum.GIFT.name())) {
      rewardPropsCO.setQuantity(reward.getQuantity());
      rewardPropsCO.setCover(getGiftConfig(reward).getGiftPhoto());
      return rewardPropsCO;
    }

    if (Objects.equals(reward.getType(), PropsTypeEnum.BADGE.name())) {
      rewardPropsCO.setQuantity(reward.getQuantity());
      rewardPropsCO.setCover(getByBadgeId(cmd, reward).getSelectUrl());
      return rewardPropsCO;
    }

    if (Objects.equals(reward.getType(), PropsTypeEnum.PROPS.name())) {
      rewardPropsCO.setQuantity(reward.getQuantity());
      rewardPropsCO.setCover(getPropsById(reward).getCover());
      return rewardPropsCO;
    }
    return null;
  }

  private PropsSourceRecord getPropsById(PropsActivityRewardConfig reward) {
    return propsSourceRecordService.getPropsById(Long.parseLong(reward.getContent()));
  }

  private BadgePictureConfig getByBadgeId(AppExtCommand cmd, PropsActivityRewardConfig reward) {
    return badgePictureConfigService
        .getByBadgeId(cmd.getReqSysOrigin().getOrigin(), Long.parseLong(reward.getContent()));
  }

  private GiftConfig getGiftConfig(PropsActivityRewardConfig reward) {
    return giftConfigService.getEffectiveById(Long.valueOf(reward.getContent()));
  }

  private ActivityRewardProps getRewardBuild(PropsActivityRewardConfig reward) {
    return new ActivityRewardProps()
        .setId(reward.getId())
        .setGroupId(reward.getGroupId())
        .setSort(reward.getSort())
        .setType(reward.getType());
  }


  private Map<Long, List<PropsActivityRewardConfig>> mapRewardsByGroupIds(
      List<PropsActivityRuleConfig> ruleConfigs) {

    return propsActivityRewardConfigService.mapGroupByIds(
        ruleConfigs.stream().map(PropsActivityRuleConfig::getResourceGroupId).collect(
            Collectors.toSet()));
  }

  private List<PropsActivityRuleConfig> listRuleConfigs(AppExtCommand cmd) {

    return propsActivityRuleConfigService.listPlatformByActivityType(
        cmd.getReqSysOrigin().getOrigin(),
        PropsActivityTypeEnum.FIRST_CHARGE_REWARD);
  }


}
