package com.kym.service.miniapp.impl;

import com.kym.entity.miniapp.Account;
import com.kym.entity.miniapp.ChargeOrder;
import com.kym.entity.miniapp.OrderRechargeRights;
import com.kym.entity.miniapp.UserRechargeRights;
import com.kym.service.miniapp.DiscountService;
import com.kym.service.miniapp.OrderRechargeRightsService;
import com.kym.service.miniapp.UserRechargeRightsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 充值优惠计算
 *
 * @author skyline
 */
@Service
@Slf4j
public class RechargeRightsDiscountHandle implements DiscountService {


    private final OrderRechargeRightsService orderRechargeRightsService;
    private final UserRechargeRightsService userRechargeRightsService;

    public RechargeRightsDiscountHandle(OrderRechargeRightsService orderRechargeRightsService, UserRechargeRightsService userRechargeRightsService) {
        this.orderRechargeRightsService = orderRechargeRightsService;
        this.userRechargeRightsService = userRechargeRightsService;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void computeDiscount(ChargeOrder chargeOrder, Account account) {
        int discountAmount;

        try {
            // 获取订单权益，计算订单优惠金额，实付金额，服务费优惠金额
            var orderRechargeRights = orderRechargeRightsService.lambdaQuery()
                    .eq(OrderRechargeRights::getStartChargeSeq, chargeOrder.getStartChargeSeq())
                    .eq(OrderRechargeRights::getUserId, chargeOrder.getUserId())
                    .one();
            if (orderRechargeRights != null) {
                // 获取折扣，计算优惠
                var discount = orderRechargeRights.getDiscount();
                // 服务费优惠金额只保留到分，分以下不进行四舍五入
                var serviceMoneyDiscount = (int) (chargeOrder.getServiceMoney() * (BigDecimal.valueOf(1).subtract(BigDecimal.valueOf(discount).divide(BigDecimal.valueOf(100)))).doubleValue());
                chargeOrder
                        .setPayAmount(chargeOrder.getTotalMoney() - serviceMoneyDiscount)
                        .setDiscountAmount(serviceMoneyDiscount)
                        .setServiceMoneyDiscount(serviceMoneyDiscount);

                orderRechargeRights.setDiscountAmount(serviceMoneyDiscount);

                // 用户充值权益
                var userRechargeRights = userRechargeRightsService.lambdaQuery()
                        .eq(UserRechargeRights::getId, orderRechargeRights.getUserRightsId())
                        .eq(UserRechargeRights::getUserId, chargeOrder.getUserId())
                        .eq(UserRechargeRights::getRightsId, orderRechargeRights.getRightsId())
                        .one();

                // 用户当前权益金余额是否足够支付本次充电费用
                if (userRechargeRights.getStatus() == UserRechargeRights.STATUS_有效) {
                    if (chargeOrder.getPayAmount() <= userRechargeRights.getRightsBalance()) {
                        userRechargeRights
                                // 用户权益包余额扣减当前订单实付金额
                                .setRightsBalance(userRechargeRights.getRightsBalance() - chargeOrder.getPayAmount())
                                .setDiscountAmount(userRechargeRights.getDiscountAmount() + serviceMoneyDiscount);

                        // 账户设置优惠不可退金额
                        discountAmount = account.getDiscountAmount() + serviceMoneyDiscount;
                        account.setDiscountAmount(discountAmount);
                        // 权益失效时更新状态
                        if (chargeOrder.getPayAmount().intValue() == userRechargeRights.getRightsBalance().intValue()) {
                            userRechargeRights.setStatus(UserRechargeRights.STATUS_无效);
                        }
                    } else {
                        // 不足(用户当前权益金余额是否足够支付本次充电费用)
                        // 如果优惠后的实付金额大于权益金余额，那么实际优惠金额需要通过权益金余额反推
                        // 通过权益金余额，反推最多扣减多少服务费
                        // rightBalance = elecMoney + serviceMoney * (1-discount)
                        // 订单中elecMoney与serviceMoney的比值是一定的
                        var ratio = BigDecimal.valueOf(chargeOrder.getElecMoney()).divide(BigDecimal.valueOf(chargeOrder.getServiceMoney()), 2, RoundingMode.HALF_UP);
                        // (ratio * realServiceMoney) + (realServiceMoney * (100 - discount)/100) = rightBalance
                        var discountRate = BigDecimal.valueOf(discount).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
                        var userRightBalance = BigDecimal.valueOf(userRechargeRights.getRightsBalance());
                        // 真实可以覆盖的服务费金额
                        var realServiceMoney = userRightBalance.divide(ratio.add(BigDecimal.valueOf(1)).subtract(discountRate), 2, RoundingMode.HALF_UP);
                        // 实际优惠金额 = 实际可以覆盖的服务费金额 * 折扣率
                        var realDiscountAmount = realServiceMoney.multiply(BigDecimal.valueOf(1).subtract(discountRate)).intValue();
                        chargeOrder
                                // 实付金额
                                .setPayAmount(chargeOrder.getTotalMoney() - realDiscountAmount)
                                .setDiscountAmount(realDiscountAmount)
                                .setServiceMoneyDiscount(realDiscountAmount);
                        // 余额扣完,总优惠金额加上最后一次真实优惠金额，此条用户权益结束，状态设置为无效
                        userRechargeRights
                                .setRightsBalance(0)
                                .setDiscountAmount(userRechargeRights.getDiscountAmount() + realDiscountAmount)
                                .setStatus(UserRechargeRights.STATUS_无效);

                        orderRechargeRights.setDiscountAmount(realDiscountAmount);
                        // 此权益包消耗完毕，账户设置优惠不可退金额
                        discountAmount = account.getDiscountAmount() + realDiscountAmount;
                        account.setDiscountAmount(discountAmount);
                    }
                }

                // 更新订单权益的最终优惠金额
                orderRechargeRightsService.updateById(orderRechargeRights);
                // 更新用户权益金等
                userRechargeRightsService.updateById(userRechargeRights);
            }


        } catch (Exception e) {
            log.error("处理充值优惠失败", e);
            // 可以添加一些错误处理逻辑，比如重试机制、发送告警等
        }
    }


}
