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

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.ss.bonus.domain.BonusVO;
import com.ruoyi.ss.bonus.domain.enums.BonusArrivalType;
import com.ruoyi.ss.bonus.service.BonusService;
import com.ruoyi.ss.payBill.domain.PayBillVO;
import com.ruoyi.ss.payBill.domain.bo.RefundSuccessBO;
import com.ruoyi.ss.payBill.domain.dto.PayBillRefundDTO;
import com.ruoyi.ss.payBill.interfaces.AfterPay;
import com.ruoyi.ss.payBill.interfaces.AfterRefund;
import com.ruoyi.ss.payBill.service.PayBillService;
import com.ruoyi.ss.suit.domain.enums.SuitFeeType;
import com.ruoyi.ss.transactionBill.domain.TransactionBill;
import com.ruoyi.ss.transactionBill.domain.TransactionBillQuery;
import com.ruoyi.ss.transactionBill.domain.bo.PaySuccessBO;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillStatus;
import com.ruoyi.ss.transactionBill.domain.enums.TransactionBillType;
import com.ruoyi.ss.transactionBill.domain.vo.TransactionBillVO;
import com.ruoyi.ss.transactionBill.service.TransactionAssembler;
import com.ruoyi.ss.transactionBill.service.TransactionBillService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

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

/**
 * 充值成功处理类
 * @author wjh
 * 2024/8/14
 */
@Service
public class RechargePayHandler implements AfterPay, AfterRefund {


    @Autowired
    private TransactionBillService transactionBillService;

    @Autowired
    private PayBillService payBillService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private ScheduledExecutorService scheduledExecutorService;

    @Autowired
    private BonusService bonusService;

    @Autowired
    private TransactionAssembler transactionAssembler;

    @Override
    public int onPaySuccess(PayBillVO payBill) {
        TransactionBillVO bill = transactionBillService.selectSmTransactionBillByBillId(payBill.getBstId());
        if (bill == null) {
            return 0;
        }

        PaySuccessBO bo = new PaySuccessBO();
        bo.setOrder(bill);
        bo.setPayBill(payBill);
        // 拼接分成列表
        transactionAssembler.assembleBonusList(bill);

        if (SuitFeeType.singleList().contains(bill.getSuitFeeType())) {
            return this.handleSinglePaySuccess(bo);
        } else {
            return this.handleTimingPaySuccess(bo);
        }
    }

    /**
     * 处理单次订单支付成功
     */
    private int handleSinglePaySuccess(PaySuccessBO bo) {
        TransactionBillVO bill = bo.getOrder();
        PayBillVO pay = bo.getPayBill();
        ServiceUtil.assertion(bill == null || !TransactionBillType.RECHARGE.getType().equals(bill.getType()), "充值订单不存在");
        ServiceUtil.assertion(!TransactionBillStatus.UNPAID.getStatus().equals(bill.getStatus()), "当前订单状态非未支付");

        List<BonusVO> bonusList = bill.getBonusList();

        Integer result = transactionTemplate.execute(status -> {
            // 处理分成，将金额分好
            bonusService.partBonus(bonusList, bill.getMoney());
            BonusVO platform = bonusList.stream().filter(bonus -> bonus.getArrivalType().equals(BonusArrivalType.PLATFORM.getType())).findFirst().orElse(null);
            BonusVO mch = bonusList.stream().filter(bonus -> bonus.getArrivalType().equals(BonusArrivalType.MCH.getType())).findFirst().orElse(null);

            // 修改订单信息
            TransactionBill data = new TransactionBill();
            data.setStatus(TransactionBillStatus.SUCCESS.getStatus());
            data.setPayTime(DateUtils.toDate(pay.getPayTime()));
            data.setChannelId(pay.getChannelId());
            data.setChannelCost(pay.getChannelCost());
            data.setPayId(pay.getPayId());
            if (platform != null) {
                data.setServiceCharge(platform.getAmount());
            }
            if (mch != null) {
                data.setArrivalAmount(mch.getAmount());
            }
            TransactionBillQuery query = new TransactionBillQuery();
            query.setBillId(bill.getBillId());
            query.setStatus(TransactionBillStatus.UNPAID.getStatus());
            query.setType(TransactionBillType.RECHARGE.getType());
            int updateCount = transactionBillService.updateByQuery(data, query);
            ServiceUtil.assertion(updateCount != 1, "订单状态已发生变化，请刷新后重试");

            // 处理商户获取手机号扣款
            int received = transactionBillService.receiveMchShowMobileAmount(bill);
            ServiceUtil.assertion(received != 1, "商户获取用户手机号扣款失败");

            return updateCount;
        });

        // 操作成功
        if (result != null && result == 1) {
            // 充值设备
            transactionBillService.rechargeDevice(bill.getBillId());

            // 5秒后，设备设置语音播报
            scheduledExecutorService.schedule(() -> {
                transactionBillService.trySetVoice(bill, 3);
            }, 5, TimeUnit.SECONDS);
        }

        return result == null ? 0 : result;
    }

    /**
     * 处理分时段订单支付成功
     */
    private int handleTimingPaySuccess(PaySuccessBO bo) {
        if (bo == null) {
            return 0;
        }

        TransactionBillVO order = bo.getOrder();
        PayBillVO pay = bo.getPayBill();

        ServiceUtil.assertion(order == null, "充值订单不存在");
        ServiceUtil.assertion(!TransactionBillStatus.UNPAID.getStatus().equals(order.getStatus()), "当前订单状态非待支付状态");

        Integer result = transactionTemplate.execute(status -> {
            // 修改订单状态
            TransactionBill data = new TransactionBill();
            data.setPayTime(DateUtils.toDate(pay.getPayTime()));
            data.setPayId(pay.getPayId());
            data.setChannelCost(pay.getChannelCost());
            data.setChannelId(pay.getChannelId());
            data.setStatus(TransactionBillStatus.SUCCESS.getStatus());
            TransactionBillQuery query = new TransactionBillQuery();
            query.setBillId(order.getBillId());
            query.setStatus(TransactionBillStatus.UNPAID.getStatus());
            int update = transactionBillService.updateByQuery(data, query);
            ServiceUtil.assertion(update != 1, "修改订单状态失败");

            // 处理分成
            bonusService.partBonus(order.getBonusList(), order.getMoney());

            // 如果有押金，则申请押金退款
            if (order.getSuitDeposit() != null && order.getSuitDeposit().compareTo(BigDecimal.ZERO) > 0 && order.getDepositPayId() != null) {
                // 押金退款
                PayBillRefundDTO refundDto = new PayBillRefundDTO();
                refundDto.setPayId(order.getDepositPayId());
                refundDto.setRefundAmount(order.getSuitDeposit());
                refundDto.setRefundReason(String.format("充值订单%s押金退款", order.getBillNo()));
                int refund = payBillService.refund(refundDto);
                ServiceUtil.assertion(refund != 1, "申请退款失败");
            }

            return update;
        });

        return result == null ? 0 : result;

    }

    @Override
    public int onRefundSuccess(RefundSuccessBO bo) {
        PayBillVO pay = bo.getPay();

        Integer result = transactionTemplate.execute(status -> {
            TransactionBill billData = new TransactionBill();
            billData.setStatus(TransactionBillStatus.REFUNDED.getStatus());
            TransactionBillQuery billQuery = new TransactionBillQuery();
            billQuery.setBillId(pay.getBstId());
            billQuery.setStatus(TransactionBillStatus.REFUNDING.getStatus());
            int updateBill = transactionBillService.updateByQuery(billData, billQuery);
            ServiceUtil.assertion(updateBill != 1, "修改原订单状态失败");

            return updateBill;
        });

        return result == null ? 0 : result;
    }
}
