package com.bonus.core.account.v3.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bonus.core.account.v3.api.AccPayBusinessApi;
import com.bonus.core.account.v3.api.dto.AccOrdBaseDTO;
import com.bonus.core.account.v3.api.dto.AccOrdRefundDTO;
import com.bonus.core.account.v3.constants.AccExceptionRecordStatusEnum;
import com.bonus.core.account.v3.mapper.AccExceptionRecordMapper;
import com.bonus.core.account.v3.model.AccExceptionRecord;
import com.bonus.core.account.v3.service.AccExceptionRecordService;
import com.bonus.core.account.v3.web.dto.AccAddExceptionRecordDTO;
import com.bonus.core.account.v3.web.dto.AccUpdateExceptionRecordDTO;
import com.bonus.core.account.v3.web.vo.AccOrdBasicsVO;
import com.bonus.core.marketing.v2.rule.price.dto.RulePriceResultDTO;
import com.bonus.core.pay.api.TradeRecordApi;
import com.bonus.core.pay.api.vo.TradeRecordParamVO;
import com.bonus.utils.id.Id;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.lang.invoke.SerializedLambda;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class AccExceptionRecordServiceImpl extends ServiceImpl<AccExceptionRecordMapper, AccExceptionRecord> implements AccExceptionRecordService {
   private static final Logger log = LoggerFactory.getLogger(AccExceptionRecordServiceImpl.class);
   @Resource
   @Lazy
   private AccPayBusinessApi accPayBusinessApi;
   @Resource
   @Lazy
   private TradeRecordApi tradeRecordApi;

   @Override
   public void addAccExceptionRecord(AccAddExceptionRecordDTO addDTO) {
      log.info("[账户异常记录]新增入参:{}", JSONUtil.toJsonStr(addDTO));
      AccExceptionRecord accExceptionRecord = new AccExceptionRecord();
      BeanUtil.copyProperties(addDTO, accExceptionRecord, new String[0]);
      accExceptionRecord.setId(Id.next());
      ((AccExceptionRecordMapper)this.baseMapper).insert(accExceptionRecord);
   }

   @Override
   @Transactional(
      rollbackFor = {Exception.class}
   )
   public void updateAccExceptionRecord(AccUpdateExceptionRecordDTO updateDTO) {
      log.info("[账户异常记录]修改入参:{}", JSONUtil.toJsonStr(updateDTO));
      AccExceptionRecord updateAccExceptionRecord = new AccExceptionRecord();
      String message = "";

      try {
         AccExceptionRecord accExceptionRecord = (AccExceptionRecord)((AccExceptionRecordMapper)this.baseMapper).selectOne((Wrapper)Wrappers.lambdaQuery(AccExceptionRecord.class).eq(AccExceptionRecord::getRelationId, updateDTO.getRelationId()));
         log.info("[账户异常记录]修改,查询异常记录,relationId={},vo={}", updateDTO.getRelationId(), JSONUtil.toJsonStr(accExceptionRecord));
         if (ObjectUtil.isNotNull(updateDTO.getOperatorType()) && updateDTO.getOperatorType() == 2) {
            this.accOrdRefundHandle(accExceptionRecord, updateDTO.getRefundAmount());
            BigDecimal subtract = accExceptionRecord.getAmount().subtract(updateDTO.getRefundAmount());
            updateAccExceptionRecord.setAmount(subtract);
            updateDTO.setRecordStatus(accExceptionRecord.getRecordStatus());
         } else if (AccExceptionRecordStatusEnum.FAIL.getKey().equals(updateDTO.getRecordStatus())) {
            AccOrdBaseDTO accOrdBaseDTO = this.assembleAccPayForOfflineDTO(accExceptionRecord);
            AccOrdBasicsVO accOrdBasicsVO = this.accPayBusinessApi.accPayForOffline(accOrdBaseDTO);
            updateAccExceptionRecord.setWalletPayAmount(accOrdBasicsVO.getWalletPay());
            updateAccExceptionRecord.setSubPayAmount(accOrdBasicsVO.getSubsidyPay());
            updateAccExceptionRecord.setRedPayAmount(accOrdBasicsVO.getRedEnvelopePay());
            updateAccExceptionRecord.setAccBal(accOrdBasicsVO.getAccBal());
         }
      } catch (Exception var7) {
         message = "|" + var7.getMessage();
      }

      updateAccExceptionRecord.setRecordStatus(updateDTO.getRecordStatus());
      String var10001 = updateDTO.getRemark();
      updateAccExceptionRecord.setRemark(var10001 + message);
      log.info("[账户异常记录]修改异常记录入参:{}", JSONUtil.toJsonStr(updateAccExceptionRecord));
      ((AccExceptionRecordMapper)this.baseMapper).update(updateAccExceptionRecord, (Wrapper)Wrappers.lambdaUpdate(AccExceptionRecord.class).eq(AccExceptionRecord::getRelationId, updateDTO.getRelationId()));
   }

   public AccOrdBaseDTO assembleAccPayForOfflineDTO(AccExceptionRecord accExceptionRecord) {
      AccOrdBaseDTO accPayDTO = (AccOrdBaseDTO)BeanUtil.copyProperties(this, AccOrdBaseDTO.class, new String[0]);
      accPayDTO.setCustId(accExceptionRecord.getCustId());
      accPayDTO.setOrderId(accExceptionRecord.getRelationId());
      accPayDTO.setRulePriceResult((new RulePriceResultDTO()).setRealAmount(accExceptionRecord.getAmount()));
      TradeRecordParamVO tradeRecordOrderInfo = this.tradeRecordApi.getParamVOByTradeId(accExceptionRecord.getRelationId());
      if (ObjectUtil.isNotNull(tradeRecordOrderInfo)) {
         accPayDTO.setCanteenId(tradeRecordOrderInfo.getCanteenId());
         accPayDTO.setCanteenName(tradeRecordOrderInfo.getCanteenName());
         accPayDTO.setShopstallId(tradeRecordOrderInfo.getStallId());
         accPayDTO.setShopstallName(tradeRecordOrderInfo.getStallName());
         accPayDTO.setMchNum(tradeRecordOrderInfo.getMchNum());
         accPayDTO.setMchSn(tradeRecordOrderInfo.getMchSn());
         accPayDTO.setOrdTime(tradeRecordOrderInfo.getOrderTime());
         accPayDTO.setNuClearMode(tradeRecordOrderInfo.getNuClearMode());
         accPayDTO.setIfOnline(tradeRecordOrderInfo.getIfOnline());
         accPayDTO.setSourceType(tradeRecordOrderInfo.getSourceType());
         accPayDTO.setOrderType(tradeRecordOrderInfo.getOrderType());
      }

      return accPayDTO;
   }


   @Override
   public boolean existExceptionRecordByRelatedId(Long relatedId, Integer recordStatus) {
      return ((AccExceptionRecordMapper)this.baseMapper).exists(Wrappers.lambdaQuery(AccExceptionRecord.class)
              .eq(AccExceptionRecord::getRelationId, relatedId)
              .eq(recordStatus != null, AccExceptionRecord::getRecordStatus, recordStatus));
   }
   protected void accOrdRefundHandle(AccExceptionRecord accExceptionRecord, BigDecimal refundAmount) {
      AccOrdRefundDTO accOrdRefundDTO = new AccOrdRefundDTO();
      accOrdRefundDTO.setOrderId(accExceptionRecord.getRelationId());
      accOrdRefundDTO.setCustId(accExceptionRecord.getCustId());
      accOrdRefundDTO.setAmount(refundAmount);
      accOrdRefundDTO.setRefundOrderId(accExceptionRecord.getRelationId());
      this.accPayBusinessApi.accOrdForRefund(accOrdRefundDTO);
   }
}
