package com.red.circle.order.app.common;

import com.red.circle.common.business.core.enums.ReceiptType;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.common.business.enums.SendPropsOrigin;
import com.red.circle.component.mq.MessageEventProcess;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.CommonErrorCode;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.framework.web.props.EnvProperties;
import com.red.circle.mq.business.model.event.pay.BuySuccessEvent;
import com.red.circle.order.app.command.pay.web.strategy.PayEnv;
import com.red.circle.order.domain.gateway.UserRechargeCountGateway;
import com.red.circle.order.infra.database.mongo.order.InAppPurchaseCollectionReceiptService;
import com.red.circle.order.infra.database.mongo.order.InAppPurchaseDetailsService;
import com.red.circle.order.infra.database.mongo.order.entity.InAppPurchaseDetails;
import com.red.circle.order.infra.database.mongo.order.entity.assist.InAppPurchaseProduct;
import com.red.circle.order.infra.database.rds.entity.order.OrderPurchaseHistory;
import com.red.circle.order.infra.database.rds.service.order.OrderPurchaseHistoryService;
import com.red.circle.order.inner.asserts.OrderErrorCode;
import com.red.circle.order.inner.model.enums.MonthlyRechargeType;
import com.red.circle.order.inner.model.enums.PayApplicationCommodityType;
import com.red.circle.order.inner.model.enums.inapp.InAppPurchaseStatus;
import com.red.circle.other.inner.endpoint.activity.AppRankCountClient;
import com.red.circle.other.inner.endpoint.activity.CumulativeRechargeClient;
import com.red.circle.other.inner.endpoint.activity.PropsActivityClient;
import com.red.circle.other.inner.endpoint.material.props.PropsToolClient;
import com.red.circle.other.inner.endpoint.sys.EnumConfigClient;
import com.red.circle.other.inner.endpoint.user.user.*;
import com.red.circle.other.inner.enums.activity.PropsActivityTypeEnum;
import com.red.circle.other.inner.model.cmd.activity.SendActivityRewardCmd;
import com.red.circle.other.inner.model.cmd.material.PrizeDescribe;
import com.red.circle.other.inner.model.cmd.material.PrizeDescribeRewardCmd;
import com.red.circle.other.inner.model.dto.activity.props.ActivityPropsRule;
import com.red.circle.other.inner.model.dto.user.UserOneTimeTaskDTO;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.json.JacksonUtils;
import com.red.circle.tool.core.text.StringUtils;
import com.red.circle.wallet.inner.endpoint.freight.FreightGoldClient;
import com.red.circle.wallet.inner.endpoint.wallet.WalletDiamondClient;
import com.red.circle.wallet.inner.endpoint.wallet.WalletGoldClient;
import com.red.circle.wallet.inner.model.cmd.FreightBalanceRunningWaterCmd;
import com.red.circle.wallet.inner.model.cmd.GoldReceiptCmd;
import com.red.circle.wallet.inner.model.enums.FreightBalanceOrigin;
import com.red.circle.wallet.inner.model.enums.GoldOrigin;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * @author pengliang on 2022/10/28
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class InAppPurchaseCommon {

  private final EnvProperties envProperties;
  private final UserSvipClient userSvipClient;
  private final InviteUserClient inviteUserClient;
  private final WalletGoldClient walletGoldClient;
  private final FreightGoldClient freightGoldClient;
  private final AppRankCountClient appRankCountClient;
  private final PropsToolClient propsRepositoryClient;
  private final CumulativeRechargeClient cumulativeRechargeClient;
  private final UserRechargeCountGateway userRechargeCountGateway;
  private final InAppPurchaseDetailsService inAppPurchaseDetailsService;
  private final OrderPurchaseHistoryService orderPurchaseHistoryService;
  private final InAppPurchaseCollectionReceiptService inAppPurchaseCollectionReceiptService;
  private final UserLevelClient userLevelClient;
  private final PropsActivityClient propsActivityClient;
  private final UserOneTimeTaskClient userOneTimeTaskClient;
  private final UserProfileClient userProfileClient;

  public void inAppPurchaseReceipt(InAppPurchaseDetails order) {

    if (!order.receiptTypeEqReceipt()) {
      return;
    }

    if (!Objects.equals(order.getStatus(), InAppPurchaseStatus.CREATE)) {
      return;
    }

    if (CollectionUtils.isEmpty(order.getProducts())) {
      inAppPurchaseCollectionReceiptService.updateStatusSuccess(order.getTrackId());
      inAppPurchaseDetailsService.updateStatus(order.getId(), InAppPurchaseStatus.SUCCESS);
      return;
    }

    saveOrderPurchaseHistory(order);

    propsRepositoryClient.sendProps(new PrizeDescribeRewardCmd()
        .setTrackId(order.longId())
        .setAcceptUserId(order.getAcceptUserId())
        .setOrigin(SendPropsOrigin.COLLECTION_RECEIPT)
        .setSysOrigin(SysOriginPlatformEnum.valueOf(order.getSysOrigin()))
        .setPrizes(
            order.getProducts().stream().map(product -> {
              String code = product.getCode();
              if (StringUtils.isBlank(code)) {
                log.warn("商品类型错误，忽略商品发送:{}", JacksonUtils.toJson(product));
                return null;
              }
              String[] codes = code.trim().split(":");
              return new PrizeDescribe()
                  .setTrackId(order.longId())
                  .setType(codes[0])
                  .setDetailType(codes.length > 1 ? codes[1] : codes[0])
                  .setContent(product.getContent())
                  .setQuantity(product.getQuantity())
                  .setRemark(GoldOrigin.WEB_BUY.getDesc());
            }).filter(Objects::nonNull).collect(Collectors.toList())
        )
    );

    inAppPurchaseCollectionReceiptService.updateStatusSuccess(order.getTrackId());
    inAppPurchaseDetailsService.updateStatus(order.getId(), InAppPurchaseStatus.SUCCESS);
  }

  public void inAppPurchasePayment(InAppPurchaseDetails order) {
    InAppPurchaseProduct product = order.firstProduct();
    ResponseAssert.notNull(CommonErrorCode.NOT_FOUND_MAPPING_INFO, product);

    saveOrderPurchaseHistory(order);

    if (PayApplicationCommodityType.GOLD.eq(product.getCode())) {
      inAppPurchase(order);
    }

    if (PayApplicationCommodityType.FREIGHT_GOLD.eq(product.getCode())) {
      inShipPurchase(order);
    }

    // 修改订单状态
    inAppPurchaseDetailsService.updateStatus(order.getId(), InAppPurchaseStatus.SUCCESS);
  }


  private void inAppPurchase(InAppPurchaseDetails order) {
    BigDecimal amount = order.firstProductContentToBigDecimal();

    walletGoldClient.changeBalance(GoldReceiptCmd.builder()
        .appIncome()
        .userId(order.getAcceptUserId())
        .eventId(order.getId())
        .sysOrigin(order.getSysOrigin())
        .origin(GoldOrigin.WEB_BUY)
        .originDescribe(order.getProductDescriptor())
        .amount(amount)
        .build());

    // 累计充值统计.
    userRechargeCountGateway.count(order.getAcceptUserId(),
        order.getAmountUsd(),
        MonthlyRechargeType.valueOf(order.getFactory().getFactoryCode()));
    appRankCountClient.incrRechargeQuantity(order.getSysOrigin(),
        order.getAcceptUserId(),
        amount.longValue());

    //计入财富榜
    userLevelClient.incrWealthExp(order.getAcceptUserId(), amount);

    // 累计今日充值，每日累计充值抽奖活动
    cumulativeRechargeClient.incrTodayRechargeScore(
        order.getAcceptUserId(),
        order.getAmountUsd().doubleValue());

    // SVip积分累计.
    userSvipClient.incrIntegral(order.getAcceptUserId(),
        amount.longValue());

    // 被邀请人充值邀请人获得佣金
    inviteUserClient.processRechargeCommission(amount,
        order.getSysOrigin(), order.getAcceptUserId());

      // 发送首充奖励
      completedFirstCharge(order.getAcceptUserId(), order.getSysOrigin());
  }

    private void completedFirstCharge(Long userId, String sysOrigin) {
        UserProfileDTO userProfileDTO = userProfileClient.getByUserId(userId).getBody();
        Duration duration = Duration.between(userProfileDTO.getCreateTime().toLocalDateTime(), LocalDateTime.now());
        if (duration.toDays() >= 7) {
            return;
        }

        ResultResponse<UserOneTimeTaskDTO> response = userOneTimeTaskClient.queryCompletedFirstCharge(userId, sysOrigin);
        if (response.checkSuccess()) {
            if (response.getBody() == null) {
                userOneTimeTaskClient.completedFirstCharge(userId, sysOrigin);

                // 发送首充奖励
                List<ActivityPropsRule> body = propsActivityClient.listRule(SysOriginPlatformEnum.valueOf(sysOrigin),
                        PropsActivityTypeEnum.FIRST_CHARGE_REWARD).getBody();
                if (body != null) {
                    ActivityPropsRule ruleConfig = body.get(0);

                    propsActivityClient.sendActivityReward(
                            new SendActivityRewardCmd()
                                    .setTrackId(ruleConfig.getId())
                                    .setOrigin(SendPropsOrigin.FIRST_CHARGE_REWARD)
                                    .setSysOrigin(SysOriginPlatformEnum.valueOf(ruleConfig.getSysOrigin()))
                                    .setSourceGroupId(ruleConfig.getResourceGroupId())
                                    .setAcceptUserId(userId)
                    );

                    userProfileClient.removeCacheAll(userId);
                }
            }
        }

    }

  private OrderPurchaseHistory saveOrderPurchaseHistory(
      InAppPurchaseDetails receipt) {

    ResponseAssert.isFalse(OrderErrorCode.ORDER_EXISTS_CREATED,
        orderPurchaseHistoryService.existById(receipt.getId()));

    OrderPurchaseHistory orderPurchaseHistory = new OrderPurchaseHistory()
        .setId(receipt.longId())
        .setSysOrigin(receipt.getSysOrigin())
        .setEvn(env())
        .setUserId(receipt.getAcceptUserId())
        .setOriginalOrderId(String.valueOf(receipt.getId()))
        .setOrderId(receipt.getOrderId())
        .setProductId(receipt.getTrackId())
        .setPurchaseProductId(receipt.getTrackId())
        .setProductDescription(receipt.getFactory().getFactoryCode() + "-" + receipt.getAmountUsd())
        .setProductType("CONSUME")
        .setPlatform(receipt.getFactory().getPlatform())
        .setPayPlatform(receipt.getFactory().getFactoryCode())
        .setUnit("USD")
        .setUnitPrice(receipt.getAmountUsd())
        .setPurchaseDateMs(TimestampUtils.now())
        .setTrialPeriod(receipt.getTrialPeriod())
        .setCreateTime(TimestampUtils.now());
    orderPurchaseHistoryService.save(orderPurchaseHistory);
    return orderPurchaseHistory;
  }

  private void inShipPurchase(InAppPurchaseDetails order) {

    BigDecimal amount = order.firstProductContentToBigDecimal();

    FreightBalanceRunningWaterCmd cmd = new FreightBalanceRunningWaterCmd()
        .setSysOrigin(SysOriginPlatformEnum.valueOf(order.getSysOrigin()))
        .setUserId(order.getAcceptUserId())
        .setAcceptUserId(order.getAcceptUserId())
        .setType(ReceiptType.INCOME)
        .setAcceptAmount(amount)
        .setUsdAmount(order.getAmountUsd())
        .setOrigin(FreightBalanceOrigin.PURCHASE)
        .setRemark(order.getFactory().getFactoryCode() + "-进货")
        .setCreateUser(order.getCreateUser());

    if (order.getFactory().getFactoryCode().equals("PAYER_MAX")) {
      cmd.setOrderAmount(order.getAmountUsd());
      cmd.setRechargeType("PAYER_MAX-进货");
    }
    freightGoldClient.changeBalance(cmd);


  }

  private String env() {
    return envProperties.isProd() ? PayEnv.PROD.name() : PayEnv.TEST.name();
  }

}
