package com.njzscloud.dispose.cst.order.helper;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.njzscloud.dispose.cst.customer.constant.SettlementWay;
import com.njzscloud.dispose.cst.order.constant.PaymentStatus;
import com.njzscloud.dispose.cst.order.pojo.entity.OrderExpenseItemsEntity;
import com.njzscloud.dispose.cst.order.pojo.entity.OrderPaymentRecordEntity;
import com.njzscloud.dispose.cst.order.service.OrderExpenseItemsService;
import com.njzscloud.dispose.cst.order.service.OrderPaymentRecordService;
import com.njzscloud.dispose.finance.constant.ExpenseStrategy;
import com.njzscloud.dispose.finance.constant.MoneyChangeCategory;
import com.njzscloud.dispose.finance.constant.Unit;
import com.njzscloud.dispose.finance.pojo.entity.MoneyAccountEntity;
import com.njzscloud.dispose.finance.pojo.entity.MoneyFlowEntity;
import com.njzscloud.dispose.finance.service.MoneyAccountService;
import com.njzscloud.dispose.finance.service.MoneyFlowService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 付费记录业务处理帮助类
 *
 * @author ljw
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class PaymentRecordHelper {

    private final OrderPaymentRecordService orderPaymentRecordService;
    private final OrderExpenseItemsService orderExpenseItemsService;
    private final MoneyAccountService moneyAccountService;
    private final MoneyFlowService moneyFlowService;

    /**
     * 更新付费记录的量,计算结算金额并支付
     *
     * @param transId       运输记录ID
     * @param settleWeight  净重（单位：千克）
     * @param transDistance 运距（单位：米）
     * @param orderSn       订单编号（用于资金流水）
     * @param trainNum      车次（用于资金流水）
     * @return 该运输记录下的所有付费记录是否都已完成（支付状态为免费或已支付）
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePaymentRecordQuantity(Long transId, Integer settleWeight, Integer transDistance, String orderSn, Integer trainNum) {
        // 1. 通过运输信息ID查询付费记录
        List<OrderPaymentRecordEntity> paymentRecords = orderPaymentRecordService.list(
            Wrappers.<OrderPaymentRecordEntity>lambdaQuery()
                .eq(OrderPaymentRecordEntity::getTransId, transId));

        if (paymentRecords.isEmpty()) {
            return true;
        }

        // 2. 遍历更新每条付费记录的量
        for (OrderPaymentRecordEntity record : paymentRecords) {
            // 通过付费记录的订单收费项 Id 查询付费项
            OrderExpenseItemsEntity expenseItem = orderExpenseItemsService.getById(record.getExpenseItemId());
            Unit unit = expenseItem.getUnit();
            ExpenseStrategy expenseStrategy = expenseItem.getExpenseStrategy();

            // 3. 根据单位计算量
            BigDecimal quantity = calculateQuantity(unit, settleWeight, transDistance);
            if (quantity == null) {
                // 单位为方，暂不处理
                continue;
            }

            // 4. 计算总金额
            BigDecimal totalMoney = calculateTotalMoney(expenseStrategy, expenseItem, quantity);

            // 5. 计算结算金额（discountMoney、reviseMoney 可为正负，直接做加法）
            BigDecimal discountMoney = record.getDiscountMoney() != null ? record.getDiscountMoney() : BigDecimal.ZERO;
            BigDecimal reviseMoney = record.getReviseMoney() != null ? record.getReviseMoney() : BigDecimal.ZERO;
            BigDecimal settleMoney = totalMoney.add(discountMoney).add(reviseMoney);

            // 6. 更新付费记录
            OrderPaymentRecordEntity updateRecord = new OrderPaymentRecordEntity();
            updateRecord.setId(record.getId());
            updateRecord.setQuantity(quantity);
            updateRecord.setTotalMoney(totalMoney);
            updateRecord.setSettleMoney(settleMoney);
            orderPaymentRecordService.updateById(updateRecord);

            // 7. 处理支付完成
            if (ExpenseStrategy.MianFei.equals(expenseStrategy)) {
                // 免费
                OrderPaymentRecordEntity payRecord = new OrderPaymentRecordEntity();
                payRecord.setId(record.getId());
                payRecord.setPaymentStatus(PaymentStatus.MianFei);
                payRecord.setPayTime(LocalDateTime.now());
                orderPaymentRecordService.updateById(payRecord);
            } else {
                // 非免费，需要处理支付
                SettlementWay settlementWay = record.getSettlementWay();
                if (SettlementWay.YueJie.equals(settlementWay) || SettlementWay.YuE.equals(settlementWay)) {
                    // 月结/余额结算
                    this.deductPayment(record, settleMoney, orderSn, trainNum);
                    OrderPaymentRecordEntity payRecord = new OrderPaymentRecordEntity();
                    payRecord.setId(record.getId());
                    payRecord.setPaymentStatus(PaymentStatus.YiZhiFu);
                    payRecord.setPayTime(LocalDateTime.now());
                    orderPaymentRecordService.updateById(payRecord);
                }
            }
        }

        // 8. 检查该运输记录下所有付费记录是否都已完成
        List<OrderPaymentRecordEntity> updatedRecords = orderPaymentRecordService.list(
            Wrappers.<OrderPaymentRecordEntity>lambdaQuery()
                .eq(OrderPaymentRecordEntity::getTransId, transId));

        boolean allCompleted = updatedRecords.stream()
            .allMatch(r -> PaymentStatus.MianFei.equals(r.getPaymentStatus()) || PaymentStatus.YiZhiFu.equals(r.getPaymentStatus()));

        log.info("运输记录 {} 的付费记录量更新完成，所有记录已完成: {}", transId, allCompleted);
        return allCompleted;
    }

    /**
     * 扣减付款人资金账户并记录流水
     *
     * @param record     付费记录
     * @param settleMoney 结算金额（支付金额）
     * @param orderSn     订单编号
     * @param trainNum    车次
     */
    private void deductPayment(OrderPaymentRecordEntity record, BigDecimal settleMoney, String orderSn, Integer trainNum) {
        Long moneyAccountId = record.getPayerMoneyAccountId();
        if (moneyAccountId == null) {
            log.warn("付费记录 {} 缺少资金账户ID，无法扣款", record.getId());
            return;
        }

        MoneyAccountEntity accountEntity = moneyAccountService.getById(moneyAccountId);
        if (accountEntity == null) {
            log.warn("资金账户 {} 不存在，无法扣款", moneyAccountId);
            return;
        }

        BigDecimal beforeBalance = accountEntity.getRecharge();
        BigDecimal afterBalance = beforeBalance.subtract(settleMoney);

        // 更新资金账户余额
        accountEntity.setRecharge(afterBalance);
        moneyAccountService.updateById(accountEntity);

        // 记录资金流水
        MoneyFlowEntity flowEntity = new MoneyFlowEntity()
            .setOrderId(record.getOrderId())
            .setOrderSn(orderSn)
            .setTrainNum(trainNum)
            .setMoneyAccountId(moneyAccountId)
            .setBeforeBalance(beforeBalance)
            .setDelta(settleMoney.negate())  // 支出为负
            .setAfterBalance(afterBalance)
            .setMoneyChangeCategory(MoneyChangeCategory.ZhiFu)
            .setMemo("订单支付");
        moneyFlowService.save(flowEntity);

        log.info("资金账户 {} 扣款成功，扣款前余额：{}，扣款金额：{}，扣款后余额：{}",
            moneyAccountId, beforeBalance, settleMoney, afterBalance);
    }

    /**
     * 计算总金额
     *
     * @param expenseStrategy 计费策略
     * @param expenseItem     付费项配置
     * @param quantity        量
     * @return 总金额
     */
    private BigDecimal calculateTotalMoney(ExpenseStrategy expenseStrategy, OrderExpenseItemsEntity expenseItem, BigDecimal quantity) {
        return switch (expenseStrategy) {
            case MianFei -> BigDecimal.ZERO;  // 免费
            case TanXing -> {                 // 弹性计费
                BigDecimal initialPrice = expenseItem.getInitialPrice();
                Integer initialQuantity = expenseItem.getInitialQuantity();
                Integer everyQuantity = expenseItem.getEveryQuantity();
                BigDecimal unitPrice = expenseItem.getUnitPrice();

                if (quantity.compareTo(BigDecimal.valueOf(initialQuantity)) <= 0) {
                    // 净重 <= 起步量，总价 = 起步价
                    yield initialPrice;
                } else {
                    // 净重 > 起步量，计算超出部分的档次
                    BigDecimal exceededQuantity = quantity.subtract(BigDecimal.valueOf(initialQuantity));
                    int tiers = (int) Math.ceil(exceededQuantity.doubleValue() / everyQuantity);
                    yield initialPrice.add(unitPrice.multiply(BigDecimal.valueOf(tiers)));
                }
            }
            case GuDing -> expenseItem.getUnitPrice();  // 固定价格
            case DanJia -> expenseItem.getUnitPrice().multiply(quantity);  // 单价计费
        };
    }

    /**
     * 根据单位计算量
     *
     * @param unit          单位
     * @param settleWeight  净重（单位：千克）
     * @param transDistance 运距（单位：米）
     * @return 量，单位为BigDecimal；返回null表示暂不处理（如方）
     */
    private BigDecimal calculateQuantity(Unit unit, Integer settleWeight, Integer transDistance) {
        if (unit == null) {
            return null;
        }
        return switch (unit) {
            case Che -> BigDecimal.ONE;                              // 车：量为1
            case Fang -> null;                                       // 方：暂不处理
            case GongLi -> transDistance != null
                ? BigDecimal.valueOf(transDistance).divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP)  // 公里：米转公里
                : null;
            case Dun -> settleWeight != null
                ? BigDecimal.valueOf(settleWeight).divide(BigDecimal.valueOf(1000), 2, RoundingMode.HALF_UP)   // 吨：千克转吨
                : null;
        };
    }

}
