package com.red.circle.order.app.command.pay.web;

import com.red.circle.component.pay.PayProperties;
import com.red.circle.component.pay.paymax.PayMaxErrorCode;
import com.red.circle.component.pay.paymax.PayMaxUtils;
import com.red.circle.component.pay.paymax.service.PayMaxRefundNotice;
import com.red.circle.component.pay.paymax.service.PayMaxResponse;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.CommonErrorCode;
import com.red.circle.framework.web.spring.ApplicationRequestUtils;
import com.red.circle.order.app.common.RecycleReimburseOrderProductCommon;
import com.red.circle.order.app.convertor.PayAppConvertor;
import com.red.circle.order.app.dto.clientobject.PayMaxResponseCO;
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.InAppPurchaseEventNotice;
import com.red.circle.order.inner.model.enums.inapp.InAppPurchaseStatus;
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 java.nio.charset.StandardCharsets;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * pay max 退款通知.
 *
 * @author pengliang on 2021/7/12
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class PayerMaxServerNoticeRefundNoticeCmdExe {

  private final PayProperties payProperties;
  private final PayAppConvertor payAppConvertor;
  private final InAppPurchaseDetailsService inAppPurchaseDetailsService;
  private final RecycleReimburseOrderProductCommon recycleReimburseOrderProductCommon;

  public PayMaxResponseCO execute(byte[] body) {

    String sign = ApplicationRequestUtils.getRequest().getHeader("sign");

    if (StringUtils.isBlank(sign)) {
      return payAppConvertor.toPayMaxResponseCO(
          PayMaxResponse.createFail(PayMaxErrorCode.SIGNATURE_ERROR));
    }

    if (!(Objects.nonNull(body) && body.length > 0)) {
      return payAppConvertor.toPayMaxResponseCO(
          PayMaxResponse.createFail(PayMaxErrorCode.PARAM_ERROR));
    }

    String bodyParam = new String(body, StandardCharsets.UTF_8);
    log.warn("sign={}、param={}", sign, bodyParam);

    PayMaxRefundNotice refundNotice = PayMaxRefundNotice.serializable(bodyParam);

    // 验证签名失败
    ResponseAssert.isTrue(CommonErrorCode.VERIFY_SIGNATURE_FAILURE,
        PayMaxUtils.validSignRsa(bodyParam, sign,
            payProperties.getPayerMax().getPlatformRsaPublicKey()));

    InAppPurchaseDetails order = inAppPurchaseDetailsService.getById(refundNotice.getOrderId());

    if (Objects.isNull(order)) {
      log.warn("PayerMax退款通知， 没有找到订单信息忽律处理:{}", JacksonUtils.toJson(refundNotice));
      return payAppConvertor.toPayMaxResponseCO(PayMaxResponse.createSuccess());
    }

    if (Objects.equals(order.getStatus(), InAppPurchaseStatus.REFUND)) {
      log.warn("PayerMax退款通知， 订单已处理:{}", JacksonUtils.toJson(refundNotice));
      return payAppConvertor.toPayMaxResponseCO(PayMaxResponse.createSuccess());
    }

    inAppPurchaseDetailsService.addPayNotices(
        refundNotice.getOrderId(),
        new InAppPurchaseEventNotice()
            .setEventId("custom-" + refundNotice.getRefundId())
            .setNoticeType("REFUND")
            .setNoticeData(refundNotice)
            .setCreateTime(TimestampUtils.now())
    );

    recycleReimburseOrderProductCommon.recycleAppOrderId(refundNotice.getOrderId());
    return payAppConvertor.toPayMaxResponseCO(PayMaxResponse.createSuccess());
  }
}
