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.PayMaxReceivePaymentNotice;
import com.red.circle.component.pay.paymax.service.PayMaxResponse;
import com.red.circle.framework.web.spring.ApplicationRequestUtils;
import com.red.circle.order.app.common.InAppPurchaseCommon;
import com.red.circle.order.app.convertor.PayAppConvertor;
import com.red.circle.order.app.dto.clientobject.PayMaxResponseCO;
import com.red.circle.order.app.dto.clientobject.PayerMaxResponseV2CO;
import com.red.circle.order.app.enums.PayMaxV2ErrorCode;
import com.red.circle.order.domain.order.PayerMaxReceivePaymentNotice;
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.InAppPurchaseEventNotice;
import com.red.circle.order.inner.model.enums.inapp.InAppPayerPurchaseStatus;
import com.red.circle.order.inner.model.enums.inapp.InAppPurchaseStatus;
import com.red.circle.tool.core.date.TimestampUtils;
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 PayerMaxServerNoticeReceivePaymentCmdExe {

  private final PayProperties payProperties;
  private final PayAppConvertor payAppConvertor;
  private final InAppPurchaseCommon inAppPurchaseCommon;
  private final InAppPurchaseDetailsService inAppPurchaseDetailsService;
  private final InAppPurchaseCollectionReceiptService inAppPurchaseCollectionReceiptService;

  public PayerMaxResponseV2CO execute(byte[] body) {

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

    if (StringUtils.isBlank(sign)) {
      return PayerMaxResponseV2CO.createFail(PayMaxV2ErrorCode.SIGNATURE_ERROR);
    }

    if (!(Objects.nonNull(body) && body.length > 0)) {
      return PayerMaxResponseV2CO.createFail(PayMaxV2ErrorCode.PARAM_ERROR);
    }

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

    PayerMaxReceivePaymentNotice paymentNotice = PayerMaxReceivePaymentNotice.serializable(bodyParam);
    // 1014 数据异常
    if (Objects.isNull(paymentNotice)) {
      return PayerMaxResponseV2CO.createFail(PayMaxV2ErrorCode.PARAM_ERROR);
    }

    Boolean validSign = PayMaxUtils.validSignRsa(bodyParam, sign,
        payProperties.getPayerMax().getPlatformRsaPublicKey());

    // 1018 验证签名失败
    if (!Objects.equals(validSign, Boolean.TRUE)) {
      return PayerMaxResponseV2CO.createFail(PayMaxV2ErrorCode.SIGNATURE_ERROR);
    }

    InAppPurchaseDetails order = inAppPurchaseDetailsService.getById(
        paymentNotice.getData().getOutTradeNo());

    if (Objects.isNull(order)) {
      log.warn("PayerMax 没有找到订单信息.");
      return PayerMaxResponseV2CO.createFail(PayMaxV2ErrorCode.ORDER_NOT_FOUND);
    }

    if (!Objects.equals(order.getStatus(), InAppPurchaseStatus.CREATE)) {
      log.warn("PayerMax 订单已处理.");
      return PayerMaxResponseV2CO.success(PayMaxV2ErrorCode.SUCCESS);
    }

    inAppPurchaseDetailsService.addPayNotices(order.getId(),
        new InAppPurchaseEventNotice()
            .setEventId(sign)
            .setNoticeType("notice-" + paymentNotice.getData().getStatus())
            .setNoticeData(paymentNotice)
            .setCreateTime(TimestampUtils.now())
    );

    // status=1 成功
    if (Objects.equals(InAppPayerPurchaseStatus.SUCCESS.name(), paymentNotice.getData().getStatus())) {
      // 1031 订单已创建
      if (!Objects.equals(order.statusEqCreate(), Boolean.TRUE)) {
        return PayerMaxResponseV2CO.createFail(PayMaxV2ErrorCode.ORDER_EXISTS_CREATED);
        /*return payAppConvertor.toPayMaxResponseV2CO(
            PayMaxResponse.createFail(PayMaxErrorCode.ORDER_EXISTS_CREATED));*/
      }

      // 收款单
      if (order.receiptTypeEqReceipt()) {
        inAppPurchaseCommon.inAppPurchaseReceipt(order);
        return PayerMaxResponseV2CO.success(PayMaxV2ErrorCode.SUCCESS);
        //return payAppConvertor.toPayMaxResponseV2CO(PayMaxResponse.createSuccess());
      }

      // 付款
      if (order.receiptTypeEqPayment()) {
        inAppPurchaseCommon.inAppPurchasePayment(order);
        return PayerMaxResponseV2CO.success(PayMaxV2ErrorCode.SUCCESS);
        //return payAppConvertor.toPayMaxResponseV2CO(PayMaxResponse.createSuccess());
      }

      throw new IllegalArgumentException("Document type error, out of scope");
    }

    // status=2 失败
    if (Objects.equals(InAppPayerPurchaseStatus.FAILED.name(), paymentNotice.getData().getStatus())) {
      if (order.receiptTypeEqReceipt()) {
        inAppPurchaseCollectionReceiptService.updateStatusSuccessFail(order.getId());
      }
      inAppPurchaseDetailsService.updateStatusReason(order.getId(), InAppPurchaseStatus.FAIL,
          String.format("%s: %s", paymentNotice.getData().getStatus(), paymentNotice.getMsg()));

      return PayerMaxResponseV2CO.success(PayMaxV2ErrorCode.SUCCESS);
      //return payAppConvertor.toPayMaxResponseV2CO(PayMaxResponse.createSuccess());
    }

    log.error("payer max status not range.");
    return PayerMaxResponseV2CO.success(PayMaxV2ErrorCode.SUCCESS);
  }

  public PayMaxResponseCO executeOld(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("old sign={}, body={}", sign, bodyParam);

    PayMaxReceivePaymentNotice paymentNotice = PayMaxReceivePaymentNotice.serializable(bodyParam);
    //PayerMaxReceivePaymentNotice paymentNotice = PayerMaxReceivePaymentNotice.serializable(bodyParam);
    // 1014 数据异常
    if (Objects.isNull(paymentNotice)) {
      return payAppConvertor.toPayMaxResponseCO(
              PayMaxResponse.createFail(PayMaxErrorCode.PARAM_ERROR));
    }

    Boolean validSign = PayMaxUtils.validSignRsa(bodyParam, sign,
            payProperties.getPayerMax().getPlatformRsaPublicKey());

    // 1018 验证签名失败
    if (!Objects.equals(validSign, Boolean.TRUE)) {
      return payAppConvertor.toPayMaxResponseCO(
              PayMaxResponse.createFail(PayMaxErrorCode.SIGNATURE_ERROR));
    }

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

    if (Objects.isNull(order)) {
      log.warn("old PayerMax 没有找到订单信息.");
      return payAppConvertor.toPayMaxResponseCO(
              PayMaxResponse.createFail(PayMaxErrorCode.ORDER_NOT_FOUND));
    }

    if (!Objects.equals(order.getStatus(), InAppPurchaseStatus.CREATE)) {
      log.warn("old PayerMax 订单已处理.");
      return payAppConvertor.toPayMaxResponseCO(
              PayMaxResponse.createFail(PayMaxErrorCode.SUCCESS));
    }

    inAppPurchaseDetailsService.addPayNotices(order.getId(),
            new InAppPurchaseEventNotice()
                    .setEventId(paymentNotice.getSign())
                    .setNoticeType("notice-" + paymentNotice.getStatus())
                    .setNoticeData(paymentNotice)
                    .setCreateTime(TimestampUtils.now())
    );

    // status=1 成功
    if (Objects.equals(1, paymentNotice.getStatus())) {
      // 1031 订单已创建
      if (!Objects.equals(order.statusEqCreate(), Boolean.TRUE)) {
        return payAppConvertor.toPayMaxResponseCO(
            PayMaxResponse.createFail(PayMaxErrorCode.ORDER_EXISTS_CREATED));
      }

      // 收款单
      if (order.receiptTypeEqReceipt()) {
        inAppPurchaseCommon.inAppPurchaseReceipt(order);
        return payAppConvertor.toPayMaxResponseCO(PayMaxResponse.createSuccess());
      }

      // 付款
      if (order.receiptTypeEqPayment()) {
        inAppPurchaseCommon.inAppPurchasePayment(order);
        return payAppConvertor.toPayMaxResponseCO(PayMaxResponse.createSuccess());
      }

      throw new IllegalArgumentException("Document type error, out of scope");
    }

    // status=2 失败
    if (Objects.equals(2, paymentNotice.getStatus())) {
      if (order.receiptTypeEqReceipt()) {
        inAppPurchaseCollectionReceiptService.updateStatusSuccessFail(order.getId());
      }
      inAppPurchaseDetailsService.updateStatusReason(order.getId(), InAppPurchaseStatus.FAIL,
              String.format("%s: %s", paymentNotice.getStatus(), paymentNotice.getErrorMsg()));

      return payAppConvertor.toPayMaxResponseCO(PayMaxResponse.createSuccess());
    }

    log.error("old payer max status not range.");
    return payAppConvertor.toPayMaxResponseCO(PayMaxResponse.createSuccess());
  }

}
