package com.bonus.canteen.core.pay.common.po;

import com.bonus.canteen.core.common.utils.TenantContextHolder;
import com.bonus.canteen.core.pay.common.constants.PayStateEnum;
import com.bonus.canteen.core.pay.common.model.TradeRecord;
import com.bonus.canteen.core.pay.common.vo.TradeChannelVO;
import com.bonus.common.houqin.framework.config.deserializer.DateTimeDeserializer;
import com.bonus.common.houqin.framework.config.serializer.DateTimeSerializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

public class RefundResultPO {
   private Long refundTradeId;
   private String traceId;
   private Long merchantId;
   private String outTradeNo;
   private Integer payState;
   private Integer payChannel;
   private Integer tradeType;
   private BigDecimal amount;
   @JsonSerialize(
      using = DateTimeSerializer.YYYY_MM_DD_HH_MM_SS.class
   )
   @JsonDeserialize(
      using = DateTimeDeserializer.class
   )
   private LocalDateTime tradeTime;
   private List<TradeChannelVO> detailList;

   public static RefundResultPO of(TradeRecord tradeRecord, List<TradeChannelVO> tradeChannels) {
      RefundResultPO payResultPO = new RefundResultPO();
      if (tradeRecord == null) {
         payResultPO.setPayState(PayStateEnum.PAY_FAIL.getKey());
         return payResultPO;
      } else {
         payResultPO.setRefundTradeId(tradeRecord.getId());
         payResultPO.setOutTradeNo(tradeRecord.getOutTradeNo());
         payResultPO.setPayState(tradeRecord.getTradeState());
         payResultPO.setPayChannel(tradeRecord.getPayChannel());
         payResultPO.setAmount(tradeRecord.getAmount());
         payResultPO.setMerchantId(TenantContextHolder.getTenantId());
         payResultPO.setTradeType(tradeRecord.getTradeType());
         payResultPO.setTradeTime(tradeRecord.getCreateTime());
         payResultPO.setDetailList(tradeChannels);
         return payResultPO;
      }
   }

   public BigDecimal calcRealAmount() {
      return PayStateEnum.isPaidState(this.payState) ? (BigDecimal)this.detailList.stream().filter((s) -> {
         return PayStateEnum.isPaySuccessState(s.getTradeState());
      }).map(TradeChannelVO::getAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add) : BigDecimal.ZERO;
   }

   public Long getRefundTradeId() {
      return this.refundTradeId;
   }

   public String getTraceId() {
      return this.traceId;
   }

   public Long getMerchantId() {
      return this.merchantId;
   }

   public String getOutTradeNo() {
      return this.outTradeNo;
   }

   public Integer getPayState() {
      return this.payState;
   }

   public Integer getPayChannel() {
      return this.payChannel;
   }

   public Integer getTradeType() {
      return this.tradeType;
   }

   public BigDecimal getAmount() {
      return this.amount;
   }

   public LocalDateTime getTradeTime() {
      return this.tradeTime;
   }

   public List<TradeChannelVO> getDetailList() {
      return this.detailList;
   }

   public void setRefundTradeId(final Long refundTradeId) {
      this.refundTradeId = refundTradeId;
   }

   public void setTraceId(final String traceId) {
      this.traceId = traceId;
   }

   public void setMerchantId(final Long merchantId) {
      this.merchantId = merchantId;
   }

   public void setOutTradeNo(final String outTradeNo) {
      this.outTradeNo = outTradeNo;
   }

   public void setPayState(final Integer payState) {
      this.payState = payState;
   }

   public void setPayChannel(final Integer payChannel) {
      this.payChannel = payChannel;
   }

   public void setTradeType(final Integer tradeType) {
      this.tradeType = tradeType;
   }

   public void setAmount(final BigDecimal amount) {
      this.amount = amount;
   }

   @JsonDeserialize(
      using = DateTimeDeserializer.class
   )
   public void setTradeTime(final LocalDateTime tradeTime) {
      this.tradeTime = tradeTime;
   }

   public void setDetailList(final List<TradeChannelVO> detailList) {
      this.detailList = detailList;
   }
}
