package com.ruoyi.ss.refund.service.impl;

import com.ruoyi.common.domain.vo.LocalDateDecimalVO;
import com.ruoyi.common.pay.PayApi;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.SnowFlakeUtil;
import com.ruoyi.ss.app.domain.AppVO;
import com.ruoyi.ss.app.service.AppService;
import com.ruoyi.ss.channel.domain.ChannelVO;
import com.ruoyi.ss.channel.domain.enums.ChannelApiType;
import com.ruoyi.ss.channel.service.ChannelConverter;
import com.ruoyi.ss.channel.service.ChannelService;
import com.ruoyi.ss.payBill.service.PayBillService;
import com.ruoyi.ss.refund.domain.Refund;
import com.ruoyi.ss.refund.domain.RefundQuery;
import com.ruoyi.ss.refund.domain.RefundVO;
import com.ruoyi.ss.refund.domain.enums.RefundStatus;
import com.ruoyi.ss.refund.mapper.RefundMapper;
import com.ruoyi.ss.refund.service.RefundService;
import com.ruoyi.ss.transactionBill.service.TransactionBillService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 退款订单Service业务层处理
 *
 * @author ruoyi
 * @date 2024-07-09
 */
@Service
public class RefundServiceImpl implements RefundService
{
    @Autowired
    private RefundMapper refundMapper;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private TransactionBillService transactionBillService;

    @Autowired
    private PayBillService payBillService;

    @Autowired
    private ScheduledExecutorService scheduledExecutorService;

    @Autowired
    private ChannelService channelService;

    @Autowired
    private ChannelConverter channelConverter;

    @Autowired
    private AppService appService;


    /**
     * 查询退款订单
     *
     * @param refundId 退款订单主键
     * @return 退款订单
     */
    @Override
    public RefundVO selectRefundByRefundId(Long refundId)
    {
        return refundMapper.selectRefundByRefundId(refundId);
    }

    /**
     * 查询退款订单列表
     *
     * @param refund 退款订单
     * @return 退款订单
     */
    @Override
    public List<RefundVO> selectRefundList(RefundQuery refund)
    {
        return refundMapper.selectRefundList(refund);
    }

    /**
     * 新增退款订单
     *
     * @param refund 退款订单
     * @return 结果
     */
    @Override
    public int insertRefund(Refund refund)
    {
        refund.setCreateTime(DateUtils.getNowDate());
        refund.setRefundNo(String.valueOf(SnowFlakeUtil.newId()));
        return refundMapper.insertRefund(refund);
    }

    /**
     * 修改退款订单
     *
     * @param refund 退款订单
     * @return 结果
     */
    @Override
    public int updateRefund(Refund refund)
    {
        return refundMapper.updateRefund(refund);
    }

    /**
     * 批量删除退款订单
     *
     * @param refundIds 需要删除的退款订单主键
     * @return 结果
     */
    @Override
    public int deleteRefundByRefundIds(Long[] refundIds)
    {
        return refundMapper.deleteRefundByRefundIds(refundIds);
    }

    /**
     * 删除退款订单信息
     *
     * @param refundId 退款订单主键
     * @return 结果
     */
    @Override
    public int deleteRefundByRefundId(Long refundId)
    {
        return refundMapper.deleteRefundByRefundId(refundId);
    }

    @Override
    public RefundVO selectRefundByRefundNo(String refundNo) {
        RefundQuery query = new RefundQuery();
        query.setRefundNo(refundNo);
        return this.selectOne(query);
    }

    @Override
    public RefundVO selectOne(RefundQuery query) {
        return refundMapper.selectOne(query);
    }

    @Override
    public void handleRefundSuccess(String refundNo) {
        ServiceUtil.assertion(StringUtils.isBlank(refundNo), "退款订单编号不允许为空");

        RefundVO refund = this.selectRefundByRefundNo(refundNo);
        ServiceUtil.assertion(refund == null, "退款订单不存在");

        transactionTemplate.execute(status -> {
            // 退款订单修改状态
            Refund refundData = new Refund();
            refundData.setStatus(RefundStatus.REFUND_SUCCESS.getStatus());
            RefundQuery refundQuery = new RefundQuery();
            refundQuery.setRefundId(refund.getRefundId());
            refundQuery.setStatus(RefundStatus.REFUNDING.getStatus());
            int updateRefund = this.updateByQuery(refundData, refundQuery);
            ServiceUtil.assertion(updateRefund != 1, "修改退款订单状态失败");

            // 处理支付单
            RefundVO newRefund = this.selectRefundByRefundNo(refundNo);
            int handleResult = payBillService.handleRefundSuccess(newRefund);
            ServiceUtil.assertion(handleResult != 1, "修改支付单状态失败");

            return updateRefund;
        });

    }

    @Override
    public int updateByQuery(Refund data, RefundQuery query) {
        if (query == null) {
            return 0;
        }
        return refundMapper.updateByQuery(data, query);
    }

    @Override
    public int createRefund(Refund refund) {
        Integer result = transactionTemplate.execute(status -> {
            refund.setStatus(RefundStatus.REFUNDING.getStatus());
            int insertRefund = this.insertRefund(refund);
            ServiceUtil.assertion(insertRefund != 1, "创建退款订单失败");

            RefundVO vo = this.selectRefundByRefundNo(refund.getRefundNo());

            // 获取渠道信息
            ChannelVO channel = channelService.selectSmChannelByChannelId(refund.getChannelId());
            ServiceUtil.assertion(channel == null, "ID为%s的支付渠道不存在", refund.getChannelId());

            // 获取API
            ChannelApiType channelApiType = ChannelApiType.parse(channel.getApiType());
            ServiceUtil.assertion(channelApiType == null, "当前退款API开发中，请稍后重试");
            PayApi payApi = ChannelApiType.getPayApi(channelApiType);
            ServiceUtil.assertion(payApi == null, "当前退款API开发中，请稍后重试");

            // 获取APP信息
            AppVO app = appService.selectAppById(refund.getAppId());
            ServiceUtil.assertion(app == null, "ID为%s的APP不存在", refund.getAppId());

            // 调用API退款
            payApi.refund(vo, channelConverter.toConfig(channel, app));

            // 判断是否同步通知，若是则直接处理支付成功
            if (channelApiType.getIsRefundSync() != null && channelApiType.getIsRefundSync()) {
                scheduledExecutorService.schedule(() -> {
                    this.handleRefundSuccess(refund.getRefundNo());
                }, 10, TimeUnit.SECONDS);
            }

            return insertRefund;
        });

        return result == null ? 0 : result;
    }

    @Override
    public int refreshResult(Long refundId) {
        RefundVO refund = selectRefundByRefundId(refundId);
        return this.refreshResult(refund);
    }

    @Override
    public int refreshResult(RefundVO refund) {
        if (refund == null) {
            return 0;
        }
        if (!RefundStatus.REFUNDING.getStatus().equals(refund.getStatus())) {
            return 0;
        }

        // 通联微信
//        if (ChannelEnum.TL_WX.getType().equals(refund.getChannelId())) {
//            Map<String, String> params = sybPayService.queryByOutTradeNo(refund.getRefundNo());
//            String trxStatus = params.get("trxstatus");
//            if (SybTrxStatus.isSuccess(trxStatus)) {
//                // 退款成功
//                scheduledExecutorService.schedule(() -> {
//                    this.handleRefundSuccess(refund.getRefundNo());
//                }, 0, TimeUnit.SECONDS);
//            }
//        }

        return 1;
    }

    @Override
    public List<LocalDateDecimalVO> selectDailyAmount(RefundQuery query) {
        return refundMapper.selectDailyAmount(query);
    }
}
