package com.ruoyi.web.modules.pay.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.modules.order.domain.BizOrderAftersale;
import com.ruoyi.web.modules.pay.config.WeChatPayProperties;
import com.ruoyi.web.modules.pay.constant.PayConstants;
import com.ruoyi.web.modules.pay.domain.BizPayRecord;
import com.ruoyi.web.modules.pay.domain.BizRefundRecord;
import com.ruoyi.web.modules.pay.mapper.BizPayRecordMapper;
import com.ruoyi.web.modules.pay.mapper.BizRefundRecordMapper;
import com.ruoyi.web.modules.pay.service.IOrderAftersaleRefundService;
import com.ruoyi.web.modules.pay.service.IShopWechatPayService;
import com.ruoyi.web.modules.pay.support.WeChatPaySupport;

@Service
public class OrderAftersaleRefundServiceImpl implements IOrderAftersaleRefundService
{
    @Autowired
    private BizRefundRecordMapper refundRecordMapper;

    @Autowired
    private BizPayRecordMapper payRecordMapper;

    @Autowired
    private WeChatPayProperties payProperties;

    @Autowired
    private WeChatPaySupport paySupport;

    @Autowired
    private IShopWechatPayService shopWechatPayService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void refundOnAftersaleFinish(BizOrderAftersale aftersale)
    {
        if (aftersale == null || aftersale.getAftersaleId() == null)
        {
            return;
        }
        BizRefundRecord existing = refundRecordMapper.selectByAftersaleId(aftersale.getAftersaleId());
        if (existing != null && (PayConstants.REFUND_STATUS_SUCCESS.equals(existing.getRefundStatus())
                || PayConstants.REFUND_STATUS_PROCESSING.equals(existing.getRefundStatus())))
        {
            return;
        }
        BigDecimal refundAmount = aftersale.getApplyAmount();
        if (refundAmount == null || refundAmount.compareTo(BigDecimal.ZERO) <= 0)
        {
            throw new ServiceException(PayConstants.MSG_REFUND_AMOUNT_INVALID);
        }
        BizPayRecord payRecord = payRecordMapper.selectLatestByOrderId(aftersale.getOrderId());
        if (payRecord == null || !PayConstants.PAY_STATUS_SUCCESS.equals(payRecord.getPayStatus()))
        {
            throw new ServiceException(PayConstants.MSG_REFUND_PAY_NOT_FOUND);
        }
        if (refundAmount.compareTo(payRecord.getPayAmount()) > 0)
        {
            throw new ServiceException(PayConstants.MSG_REFUND_EXCEED);
        }
        BigDecimal refunded = refundRecordMapper.sumSuccessRefundAmountByOrderId(aftersale.getOrderId());
        if (refunded == null)
        {
            refunded = BigDecimal.ZERO;
        }
        if (refunded.add(refundAmount).compareTo(payRecord.getPayAmount()) > 0)
        {
            throw new ServiceException(PayConstants.MSG_REFUND_EXCEED);
        }
        Date now = new Date();
        String outRefundNo = PayConstants.REFUND_NO_PREFIX + aftersale.getAftersaleNo();
        BizRefundRecord record = new BizRefundRecord();
        record.setAftersaleId(aftersale.getAftersaleId());
        record.setAftersaleNo(aftersale.getAftersaleNo());
        record.setOrderId(aftersale.getOrderId());
        record.setOrderNo(aftersale.getOrderNo());
        record.setPayId(payRecord.getPayId());
        record.setMemberId(aftersale.getMemberId());
        record.setShopId(aftersale.getShopId());
        record.setOutRefundNo(outRefundNo);
        record.setRefundAmount(refundAmount);
        record.setRefundStatus(PayConstants.REFUND_STATUS_PENDING);
        record.setCreateTime(now);
        record.setUpdateTime(now);
        refundRecordMapper.insert(record);
        try
        {
            String wxRefundId;
            String finalStatus;
            if (!payProperties.isRealPayEnabled())
            {
                wxRefundId = "MOCK_" + outRefundNo;
                finalStatus = PayConstants.REFUND_STATUS_SUCCESS;
            }
            else
            {
                if (StringUtils.isEmpty(payRecord.getWxTransactionId()))
                {
                    throw new ServiceException(PayConstants.MSG_REFUND_PAY_NOT_FOUND);
                }
                String mchId = shopWechatPayService.resolvePayMchId(aftersale.getShopId());
                wxRefundId = paySupport.createDomesticRefund(payRecord.getWxTransactionId(), outRefundNo,
                        payRecord.getPayAmount(), refundAmount, "售后退款", mchId);
                finalStatus = PayConstants.REFUND_STATUS_SUCCESS;
            }
            int rows = refundRecordMapper.updateForSuccess(record.getRefundId(), wxRefundId, finalStatus, now);
            if (rows <= 0)
            {
                throw new ServiceException(PayConstants.MSG_REFUND_FAILED);
            }
        }
        catch (ServiceException ex)
        {
            refundRecordMapper.updateForFail(record.getRefundId(), truncateFailReason(ex.getMessage()));
            throw ex;
        }
        catch (Exception ex)
        {
            refundRecordMapper.updateForFail(record.getRefundId(), truncateFailReason(ex.getMessage()));
            throw new ServiceException(PayConstants.MSG_REFUND_FAILED);
        }
    }

    private String truncateFailReason(String reason)
    {
        if (StringUtils.isEmpty(reason))
        {
            return PayConstants.MSG_REFUND_FAILED;
        }
        return reason.length() > 250 ? reason.substring(0, 250) : reason;
    }
}
