package com.ycwl.basic.pricing.service.impl;

import com.ycwl.basic.pricing.dto.*;
import com.ycwl.basic.pricing.entity.PriceBundleConfig;
import com.ycwl.basic.pricing.entity.PriceProductConfig;
import com.ycwl.basic.pricing.entity.PriceTierConfig;
import com.ycwl.basic.pricing.enums.ProductType;
import com.ycwl.basic.pricing.exception.PriceCalculationException;
import com.ycwl.basic.pricing.service.*;
import com.ycwl.basic.product.capability.PricingMode;
import com.ycwl.basic.product.capability.ProductTypeCapability;
import com.ycwl.basic.product.service.IProductTypeCapabilityService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 价格计算服务实现
 */
@Slf4j
@Service("pricingCalculationServiceImpl")
@RequiredArgsConstructor
public class PriceCalculationServiceImpl implements IPriceCalculationService {

    private static final String CAPABILITY_METADATA_ATTRIBUTE_KEYS = "pricingAttributeKeys";
    private static final int AMOUNT_SCALE = 2;
    private static final String UPGRADE_TYPE_ONE_PRICE = "ONE_PRICE";
    private static final String UPGRADE_TYPE_BUNDLE_DISCOUNT = "BUNDLE_DISCOUNT";
    
    private final IProductConfigService productConfigService;
    private final ICouponService couponService;
    private final IPriceBundleService bundleService;
    private final IBundleDiscountService bundleDiscountService;
    private final IDiscountDetectionService discountDetectionService;
    private final IVoucherService voucherService;
    private final IProductTypeCapabilityService productTypeCapabilityService;

    /**
     * 判断是否为按数量计价的商品
     * 重构: 使用商品类型能力配置替代硬编码
     *
     * @param productType 商品类型代码
     * @return true-按数量计价, false-固定价格
     */
    private boolean isQuantityBasedPricing(String productType) {
        ProductTypeCapability capability = productTypeCapabilityService.getCapability(productType);
        return capability.getPricingModeEnum() == PricingMode.QUANTITY_BASED;
    }

    private boolean isQuantityBasedPricing(ProductTypeCapability capability) {
        if (capability == null) {
            return false;
        }
        return capability.getPricingModeEnum() == PricingMode.QUANTITY_BASED;
    }

    @Override
    public PriceCalculationResult calculatePrice(PriceCalculationRequest request) {
        if (request.getProducts() == null || request.getProducts().isEmpty()) {
            throw new PriceCalculationException("商品列表不能为空");
        }

        request.getProducts().forEach(product -> {
            if (product.getProductType() == null) {
                throw new PriceCalculationException("商品类型不能为空");
            }
            if (product.getProductId() == null) {
                throw new PriceCalculationException("商品ID不能为空");
            }
            if (product.getPurchaseCount() == null) {
                product.setPurchaseCount(1);
            }
            if (product.getQuantity() == null) {
                product.setQuantity(1);
            }
        });
        // 计算商品价格和原价（传入景区ID以支持景区级优惠策略控制）
        PriceDetails priceDetails = calculateProductsPriceWithOriginal(request.getProducts(), request.getScenicId());
        BigDecimal totalAmount = priceDetails.getTotalAmount();
        BigDecimal originalTotalAmount = priceDetails.getOriginalTotalAmount();
        
        List<DiscountDetail> discountDetails = new ArrayList<>();
        
        // 添加限时立减折扣（如果原价 > 实际价格）
        BigDecimal limitedTimeDiscount = originalTotalAmount.subtract(totalAmount);
        if (limitedTimeDiscount.compareTo(BigDecimal.ZERO) > 0) {
            discountDetails.add(DiscountDetail.createLimitedTimeDiscount(limitedTimeDiscount));
        }
        
        // 检查打包购买优惠
        BigDecimal packagePrice = bundleService.getBundlePrice(request.getProducts());
        if (packagePrice != null && packagePrice.compareTo(totalAmount) < 0) {
            BigDecimal packageDiscount = totalAmount.subtract(packagePrice);
            discountDetails.add(DiscountDetail.createBundleDiscount(packageDiscount));
            totalAmount = packagePrice;
            log.info("使用打包购买: {}, 优惠: {}", packagePrice, packageDiscount);
        }
        
        // 构建价格计算结果
        PriceCalculationResult result = new PriceCalculationResult();
        result.setOriginalAmount(originalTotalAmount); // 原总价
        result.setSubtotalAmount(priceDetails.getTotalAmount()); // 商品小计
        result.setProductDetails(request.getProducts());
        
        // 使用新的优惠检测系统处理所有优惠（券码 + 优惠券）
        DiscountCombinationResult discountResult = calculateDiscounts(request, totalAmount);
        
        if (Boolean.TRUE.equals(discountResult.getSuccess())) {
            // 合并所有优惠详情
            List<DiscountDetail> allDiscountDetails = new ArrayList<>(discountDetails);
            if (discountResult.getDiscountDetails() != null) {
                allDiscountDetails.addAll(discountResult.getDiscountDetails());
            }
            
            // 重新排序
            allDiscountDetails.sort(Comparator.comparing(DiscountDetail::getSortOrder));
            
            // 计算总优惠金额（包括限时立减、打包购买和其他优惠）
            BigDecimal totalDiscountAmount = allDiscountDetails.stream()
                .map(DiscountDetail::getDiscountAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
            
            // 设置结果
            result.setDiscountAmount(totalDiscountAmount);
            result.setDiscountDetails(allDiscountDetails);
            result.setFinalAmount(originalTotalAmount.subtract(totalDiscountAmount));
            
            // 设置使用的券码和优惠券信息
            setUsedDiscountInfo(result, discountResult, request);
            
            // 如果是预览模式，设置可用优惠列表
            if (Boolean.TRUE.equals(request.getPreviewOnly())) {
                result.setAvailableDiscounts(discountResult.getAvailableDiscounts());
            }
            
        } else {
            log.warn("优惠计算失败: {}", discountResult.getErrorMessage());
            
            // 降级处理：仅使用基础优惠（限时立减、打包购买）
            BigDecimal totalDiscountAmount = discountDetails.stream()
                .map(DiscountDetail::getDiscountAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
            
            result.setDiscountAmount(totalDiscountAmount);
            result.setDiscountDetails(discountDetails);
            result.setFinalAmount(originalTotalAmount.subtract(totalDiscountAmount));
        }
        
        // 标记使用的优惠（仅在非预览模式下）
        if (!Boolean.TRUE.equals(request.getPreviewOnly())) {
            markDiscountsAsUsed(result, request);
        }
        
        return result;
    }
    
    @Override
    public UpgradeCheckResult checkUpgrade(UpgradeCheckRequest request) {
        if (request == null) {
            throw new PriceCalculationException("升单检测请求不能为空");
        }

        List<ProductItem> purchasedProducts = cloneProducts(request.getPurchasedProducts());
        List<ProductItem> intendingProducts = cloneProducts(request.getIntendingProducts());
        
        if (purchasedProducts.isEmpty() && intendingProducts.isEmpty()) {
            throw new PriceCalculationException("已购和待购商品列表不能同时为空");
        }
        
        normalizeProducts(purchasedProducts);
        normalizeProducts(intendingProducts);

        Long scenicId = request.getScenicId();
        PriceDetails purchasedDetails = purchasedProducts.isEmpty()
                ? new PriceDetails(BigDecimal.ZERO, BigDecimal.ZERO)
                : calculateProductsPriceWithOriginal(purchasedProducts, scenicId);
        PriceDetails intendingDetails = intendingProducts.isEmpty()
                ? new PriceDetails(BigDecimal.ZERO, BigDecimal.ZERO)
                : calculateProductsPriceWithOriginal(intendingProducts, scenicId);

        List<ProductItem> combinedProducts = new ArrayList<>();
        combinedProducts.addAll(purchasedProducts);
        combinedProducts.addAll(intendingProducts);
        PriceDetails combinedDetails = calculateProductsPriceWithOriginal(combinedProducts, scenicId);

        BigDecimal paidAmount = resolvePaidAmount(request);
        BigDecimal currentTotalAmount = calculateCurrentTotalAmount(paidAmount, intendingDetails);

        UpgradePriceSummary priceSummary = buildPriceSummary(purchasedDetails, intendingDetails, combinedDetails, paidAmount);
        UpgradeOnePriceResult onePriceResult = evaluateOnePrice(scenicId, combinedProducts, combinedDetails, paidAmount, currentTotalAmount);
        UpgradeBundleDiscountResult bundleDiscountResult = evaluateBundleDiscount(scenicId, combinedProducts, combinedDetails, paidAmount, currentTotalAmount);

        UpgradeCheckResult result = new UpgradeCheckResult();
        result.setScenicId(scenicId);
        result.setFaceId(request.getFaceId());
        result.setPriceSummary(priceSummary);
        result.setOnePriceResult(onePriceResult);
        result.setBundleDiscountResult(bundleDiscountResult);
        fillBestUpgrade(result, onePriceResult, bundleDiscountResult);
        result.setPurchasedProducts(purchasedProducts);
        result.setIntendingProducts(intendingProducts);
        return result;
    }
    
    private BigDecimal calculateProductsPrice(List<ProductItem> products) {
        BigDecimal totalAmount = BigDecimal.ZERO;
        
        for (ProductItem product : products) {
            BigDecimal itemPrice = calculateSingleProductPrice(product);
            product.setUnitPrice(itemPrice);
            
            BigDecimal subtotal = itemPrice.multiply(BigDecimal.valueOf(product.getPurchaseCount()));
            product.setSubtotal(subtotal);
            
            totalAmount = totalAmount.add(subtotal);
        }
        
        return totalAmount.setScale(2, RoundingMode.HALF_UP);
    }

    private PriceDetails calculateProductsPriceWithOriginal(List<ProductItem> products, Long scenicId) {
        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal originalTotalAmount = BigDecimal.ZERO;

        Map<String, ProductTypeCapability> capabilityCache = new HashMap<>();
        Map<String, List<String>> attributeKeysCache = new HashMap<>();

        for (ProductItem product : products) {
            String productTypeCode = product.getProductType().getCode();
            ProductTypeCapability capability = capabilityCache.computeIfAbsent(
                productTypeCode, productTypeCapabilityService::getCapability);

            // 计算实际价格和原价（传入景区ID）
            ProductPriceInfo priceInfo = calculateSingleProductPriceWithOriginal(product, scenicId, capability);

            product.setUnitPrice(priceInfo.getActualPrice());
            product.setOriginalPrice(priceInfo.getOriginalPrice());

            BigDecimal subtotal = priceInfo.getActualPrice().multiply(BigDecimal.valueOf(product.getPurchaseCount()));
            BigDecimal originalSubtotal = priceInfo.getOriginalPrice().multiply(BigDecimal.valueOf(product.getPurchaseCount()));

            product.setSubtotal(subtotal);

            totalAmount = totalAmount.add(subtotal);
            originalTotalAmount = originalTotalAmount.add(originalSubtotal);
        }

        return new PriceDetails(
                totalAmount.setScale(2, RoundingMode.HALF_UP),
                originalTotalAmount.setScale(2, RoundingMode.HALF_UP)
        );
    }

    private List<String> buildProductAttributeKeys(ProductTypeCapability capability) {
        if (capability == null || capability.getMetadata() == null) {
            return List.of();
        }

        Object rawValue = capability.getMetadata().get(CAPABILITY_METADATA_ATTRIBUTE_KEYS);
        if (rawValue == null) {
            return List.of();
        }

        Set<String> result = new LinkedHashSet<>();
        if (rawValue instanceof List<?> rawList) {
            for (Object item : rawList) {
                if (item instanceof String rawKey) {
                    addAttributeKey(result, rawKey);
                }
            }
        } else if (rawValue instanceof String rawString) {
            String[] parts = rawString.split(",");
            for (String part : parts) {
                addAttributeKey(result, part);
            }
        } else {
            log.warn("商品类型能力metadata中{}字段类型不支持: productType={}, valueType={}",
                CAPABILITY_METADATA_ATTRIBUTE_KEYS,
                capability.getProductType(),
                rawValue.getClass().getName());
        }

        return result.isEmpty() ? List.of() : List.copyOf(result);
    }

    private void addAttributeKey(Set<String> target, String rawKey) {
        if (rawKey == null) {
            return;
        }

        String key = rawKey.trim();
        if (key.isEmpty()) {
            return;
        }

        target.add(key);
    }
    
    private BigDecimal calculateSingleProductPrice(ProductItem product) {
        ProductType productType = product.getProductType();
        String productId = product.getProductId() != null ? product.getProductId() : "default";
        
        // 优先使用基于product_id的阶梯定价
        PriceTierConfig tierConfig = productConfigService.getTierConfig(
                productType.getCode(), productId, product.getQuantity());
        
        if (tierConfig != null) {
            log.debug("使用阶梯定价: productType={}, productId={}, quantity={}, price={}", 
                    productType.getCode(), productId, product.getQuantity(), tierConfig.getPrice());
            return tierConfig.getPrice();
        }
        
        // 使用基于product_id的基础配置
        try {
            PriceProductConfig baseConfig = productConfigService.getProductConfig(productType.getCode(), productId);
            if (baseConfig != null) {
                if (isQuantityBasedPricing(productType.getCode())) {
                    return baseConfig.getBasePrice().multiply(BigDecimal.valueOf(product.getQuantity()));
                } else {
                    return baseConfig.getBasePrice();
                }
            }
        } catch (Exception e) {
            log.warn("未找到具体商品配置: productType={}, productId={}, 尝试使用通用配置", 
                    productType, productId);
        }
        
        // 兜底：使用default配置
        try {
            PriceProductConfig defaultConfig = productConfigService.getProductConfig(productType.getCode(), "default");
            if (defaultConfig != null) {
                if (isQuantityBasedPricing(productType.getCode())) {
                    return defaultConfig.getBasePrice().multiply(BigDecimal.valueOf(product.getQuantity()));
                } else {
                    return defaultConfig.getBasePrice();
                }
            }
        } catch (Exception e) {
            log.warn("未找到default配置: productType={}", productType.getCode());
        }
        
        // 最后兜底：使用通用配置（向后兼容）
        List<PriceProductConfig> configs = productConfigService.getProductConfig(productType.getCode());
        if (!configs.isEmpty()) {
            PriceProductConfig baseConfig = configs.get(0); // 使用第一个配置作为默认
            if (isQuantityBasedPricing(productType.getCode())) {
                return baseConfig.getBasePrice().multiply(BigDecimal.valueOf(product.getQuantity()));
            } else {
                return baseConfig.getBasePrice();
            }
        }
        
        throw new PriceCalculationException("无法计算商品价格: " + productType.getDescription() + ", productId: " + productId);
    }

    private ProductPriceInfo calculateSingleProductPriceWithOriginal(ProductItem product, Long scenicId,
                                                                    ProductTypeCapability capability) {
        ProductType productType = product.getProductType();
        String productId = product.getProductId() != null ? product.getProductId() : "default";

        BigDecimal actualPrice;
        BigDecimal originalPrice = null;

        // 优先使用基于product_id的阶梯定价（带景区ID）
        PriceTierConfig tierConfig = productConfigService.getTierConfig(
                productType.getCode(), productId, product.getQuantity(), scenicId);

        if (tierConfig != null) {
            actualPrice = tierConfig.getPrice();
            originalPrice = tierConfig.getOriginalPrice();
            log.debug("使用阶梯定价: productType={}, productId={}, quantity={}, scenicId={}, price={}, originalPrice={}",
                    productType.getCode(), productId, product.getQuantity(), scenicId, actualPrice, originalPrice);
        } else {
            // 使用基于product_id的基础配置（带景区ID）
            try {
                PriceProductConfig baseConfig = productConfigService.getProductConfig(productType.getCode(), productId, scenicId);
                if (baseConfig != null) {
                    actualPrice = baseConfig.getBasePrice();
                    originalPrice = baseConfig.getOriginalPrice();

                    if (isQuantityBasedPricing(capability)) {
                        actualPrice = actualPrice.multiply(BigDecimal.valueOf(product.getQuantity()));
                        if (originalPrice != null) {
                            originalPrice = originalPrice.multiply(BigDecimal.valueOf(product.getQuantity()));
                        }
                    }
                } else {
                    throw new PriceCalculationException("无法找到具体商品配置");
                }
            } catch (Exception e) {
                log.warn("未找到具体商品配置: productType={}, productId={}, scenicId={}, 尝试使用通用配置",
                        productType, productId, scenicId);

                // 最后兜底：使用通用配置（向后兼容）
                List<PriceProductConfig> configs = productConfigService.getProductConfig(productType.getCode());
                if (!configs.isEmpty()) {
                    PriceProductConfig baseConfig = configs.getFirst();
                    actualPrice = baseConfig.getBasePrice();
                    originalPrice = baseConfig.getOriginalPrice();

                    if (isQuantityBasedPricing(capability)) {
                        actualPrice = actualPrice.multiply(BigDecimal.valueOf(product.getQuantity()));
                        if (originalPrice != null) {
                            originalPrice = originalPrice.multiply(BigDecimal.valueOf(product.getQuantity()));
                        }
                    }
                } else {
                    throw new PriceCalculationException("无法计算商品价格: " + productType.getDescription() + ", productId: " + productId);
                }
            }
        }

        return new ProductPriceInfo(actualPrice, originalPrice);
    }
    
    private UpgradePriceSummary buildPriceSummary(PriceDetails purchased, PriceDetails intending, PriceDetails combined, BigDecimal paidAmount) {
        UpgradePriceSummary summary = new UpgradePriceSummary();
        summary.setPurchasedOriginalAmount(purchased.getOriginalTotalAmount());
        summary.setPurchasedSubtotalAmount(purchased.getTotalAmount());
        summary.setIntendingOriginalAmount(intending.getOriginalTotalAmount());
        summary.setIntendingSubtotalAmount(intending.getTotalAmount());
        summary.setCombinedOriginalAmount(combined.getOriginalTotalAmount());
        summary.setCombinedSubtotalAmount(combined.getTotalAmount());
        summary.setPaidAmount(paidAmount);
        return summary;
    }
    
    private UpgradeOnePriceResult evaluateOnePrice(Long scenicId,
                                                   List<ProductItem> combinedProducts,
                                                   PriceDetails combinedDetails,
                                                   BigDecimal paidAmount,
                                                   BigDecimal currentTotalAmount) {
        UpgradeOnePriceResult result = new UpgradeOnePriceResult();
        result.setApplicable(false);
        
        PriceBundleConfig bundleConfig = bundleService.getBundleConfig(combinedProducts);
        if (bundleConfig == null || !matchesScenic(bundleConfig.getScenicId(), scenicId)) {
            return result;
        }
        
        BigDecimal bundlePrice = bundleConfig.getBundlePrice() != null
                ? bundleConfig.getBundlePrice()
                : combinedDetails.getTotalAmount();
        BigDecimal normalizedBundlePrice = normalizeAmount(bundlePrice);
        BigDecimal normalizedCurrentTotal = normalizeAmount(currentTotalAmount);
        BigDecimal normalizedPaidAmount = normalizeAmount(paidAmount);

        if (!isUpgradeBeneficial(normalizedCurrentTotal, normalizedBundlePrice)) {
            return result;
        }

        BigDecimal discountAmount = normalizedCurrentTotal.subtract(normalizedBundlePrice);
        BigDecimal supplementAmount = calculateSupplementAmount(normalizedBundlePrice, normalizedPaidAmount);
        if (supplementAmount.compareTo(BigDecimal.ZERO) <= 0) {
            return result;
        }
        
        result.setApplicable(true);
        result.setBundleConfigId(bundleConfig.getId());
        result.setBundleName(bundleConfig.getBundleName());
        result.setDescription(bundleConfig.getDescription());
        result.setScenicId(bundleConfig.getScenicId());
        result.setBundlePrice(normalizedBundlePrice);
        result.setDiscountAmount(discountAmount);
        result.setEstimatedFinalAmount(supplementAmount);
        return result;
    }
    
    private UpgradeBundleDiscountResult evaluateBundleDiscount(Long scenicId,
                                                               List<ProductItem> combinedProducts,
                                                               PriceDetails combinedDetails,
                                                               BigDecimal paidAmount,
                                                               BigDecimal currentTotalAmount) {
        UpgradeBundleDiscountResult result = new UpgradeBundleDiscountResult();
        result.setApplicable(false);
        
        BundleDiscountInfo bestDiscount = bundleDiscountService.getBestBundleDiscount(combinedProducts, scenicId);
        if (bestDiscount == null) {
            return result;
        }
        
        BigDecimal discountAmount = bestDiscount.getActualDiscountAmount();
        if (discountAmount == null || discountAmount.compareTo(BigDecimal.ZERO) <= 0) {
            discountAmount = bundleDiscountService.calculateBundleDiscount(bestDiscount, combinedProducts);
        }
        if (discountAmount == null || discountAmount.compareTo(BigDecimal.ZERO) <= 0) {
            return result;
        }
        
        BigDecimal normalizedPaidAmount = normalizeAmount(paidAmount);
        BigDecimal normalizedCurrentTotal = normalizeAmount(currentTotalAmount);
        BigDecimal normalizedDiscount = normalizeAmount(discountAmount);
        BigDecimal targetTotal = combinedDetails.getTotalAmount().subtract(normalizedDiscount);
        if (targetTotal.compareTo(BigDecimal.ZERO) < 0) {
            targetTotal = BigDecimal.ZERO;
        }

        if (!isUpgradeBeneficial(normalizedCurrentTotal, targetTotal)) {
            return result;
        }

        BigDecimal supplementAmount = calculateSupplementAmount(targetTotal, normalizedPaidAmount);
        if (supplementAmount.compareTo(BigDecimal.ZERO) <= 0) {
            return result;
        }

        result.setApplicable(true);
        result.setBundleConfigId(bestDiscount.getBundleConfigId());
        result.setBundleName(bestDiscount.getBundleName());
        result.setBundleDescription(bestDiscount.getBundleDescription());
        result.setDiscountType(bestDiscount.getDiscountType());
        result.setDiscountValue(bestDiscount.getDiscountValue());
        result.setDiscountAmount(normalizedDiscount);
        result.setMinQuantity(bestDiscount.getMinQuantity());
        result.setMinAmount(bestDiscount.getMinAmount());
        result.setEstimatedFinalAmount(supplementAmount);
        return result;
    }
    
    private List<ProductItem> cloneProducts(List<ProductItem> source) {
        List<ProductItem> copies = new ArrayList<>();
        if (source == null) {
            return copies;
        }
        for (ProductItem item : source) {
            if (item == null) {
                continue;
            }
            copies.add(cloneProductItem(item));
        }
        return copies;
    }
    
    private ProductItem cloneProductItem(ProductItem source) {
        ProductItem copy = new ProductItem();
        copy.setProductType(source.getProductType());
        copy.setProductId(source.getProductId());
        copy.setQuantity(source.getQuantity());
        copy.setPurchaseCount(source.getPurchaseCount());
        copy.setOriginalPrice(source.getOriginalPrice());
        copy.setUnitPrice(source.getUnitPrice());
        copy.setSubtotal(source.getSubtotal());
        copy.setScenicId(source.getScenicId());
        return copy;
    }
    
    private void normalizeProducts(List<ProductItem> products) {
        for (ProductItem product : products) {
            if (product.getProductType() == null) {
                throw new PriceCalculationException("商品类型不能为空");
            }
            if (product.getProductId() == null) {
                throw new PriceCalculationException("商品ID不能为空");
            }
            if (product.getPurchaseCount() == null) {
                product.setPurchaseCount(1);
            }
            if (product.getQuantity() == null) {
                product.setQuantity(1);
            }
        }
    }
    
    private boolean matchesScenic(String configScenicId, Long scenicId) {
        if (scenicId == null) {
            return true;
        }
        if (configScenicId == null || configScenicId.isEmpty()) {
            return true;
        }
        return configScenicId.equals(String.valueOf(scenicId));
    }

    private BigDecimal resolvePaidAmount(UpgradeCheckRequest request) {
        BigDecimal paidAmount = request != null ? request.getPaidAmount() : null;
        if (paidAmount == null) {
            throw new PriceCalculationException("已支付金额不能为空");
        }
        return normalizeAmount(paidAmount);
    }

    private BigDecimal calculateCurrentTotalAmount(BigDecimal paidAmount, PriceDetails intendingDetails) {
        BigDecimal intendingAmount = intendingDetails != null ? intendingDetails.getTotalAmount() : BigDecimal.ZERO;
        BigDecimal normalizedPaidAmount = normalizeAmount(paidAmount);
        BigDecimal normalizedIntendingAmount = normalizeAmount(intendingAmount);
        return normalizedPaidAmount.add(normalizedIntendingAmount).setScale(AMOUNT_SCALE, RoundingMode.HALF_UP);
    }

    private BigDecimal calculateSupplementAmount(BigDecimal targetTotalAmount, BigDecimal paidAmount) {
        BigDecimal normalizedTarget = normalizeAmount(targetTotalAmount);
        BigDecimal normalizedPaid = normalizeAmount(paidAmount);
        BigDecimal supplementAmount = normalizedTarget.subtract(normalizedPaid);
        if (supplementAmount.compareTo(BigDecimal.ZERO) < 0) {
            supplementAmount = BigDecimal.ZERO;
        }
        return supplementAmount.setScale(AMOUNT_SCALE, RoundingMode.HALF_UP);
    }

    private boolean isUpgradeBeneficial(BigDecimal currentTotalAmount, BigDecimal targetTotalAmount) {
        BigDecimal normalizedCurrent = normalizeAmount(currentTotalAmount);
        BigDecimal normalizedTarget = normalizeAmount(targetTotalAmount);
        return normalizedCurrent.compareTo(normalizedTarget) > 0;
    }

    private BigDecimal normalizeAmount(BigDecimal amount) {
        if (amount == null) {
            return BigDecimal.ZERO.setScale(AMOUNT_SCALE, RoundingMode.HALF_UP);
        }
        BigDecimal normalized = amount.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : amount;
        return normalized.setScale(AMOUNT_SCALE, RoundingMode.HALF_UP);
    }

    private void fillBestUpgrade(UpgradeCheckResult result,
                                 UpgradeOnePriceResult onePriceResult,
                                 UpgradeBundleDiscountResult bundleDiscountResult) {
        if (result == null) {
            return;
        }
        BigDecimal bestPayableAmount = null;
        String bestUpgradeType = null;

        if (onePriceResult != null && onePriceResult.isApplicable()) {
            bestPayableAmount = onePriceResult.getEstimatedFinalAmount();
            bestUpgradeType = UPGRADE_TYPE_ONE_PRICE;
        }
        if (bundleDiscountResult != null && bundleDiscountResult.isApplicable()) {
            BigDecimal bundlePayableAmount = bundleDiscountResult.getEstimatedFinalAmount();
            if (bestPayableAmount == null || (bundlePayableAmount != null
                    && bundlePayableAmount.compareTo(bestPayableAmount) < 0)) {
                bestPayableAmount = bundlePayableAmount;
                bestUpgradeType = UPGRADE_TYPE_BUNDLE_DISCOUNT;
            }
        }

        result.setBestPayableAmount(bestPayableAmount);
        result.setBestUpgradeType(bestUpgradeType);
    }
    
    /**
     * 计算优惠（券码 + 优惠券）
     */
    private DiscountCombinationResult calculateDiscounts(PriceCalculationRequest request, BigDecimal currentAmount) {
        try {
            // 构建优惠检测上下文
            DiscountDetectionContext context = new DiscountDetectionContext();
            context.setUserId(request.getUserId());
            context.setFaceId(request.getFaceId());
            context.setScenicId(request.getScenicId());
            context.setProducts(request.getProducts());
            context.setCurrentAmount(currentAmount);
            context.setVoucherCode(request.getVoucherCode());
            context.setAutoUseCoupon(request.getAutoUseCoupon());
            context.setAutoUseVoucher(request.getAutoUseVoucher());
            
            // 使用优惠检测服务计算最优组合
            if (Boolean.TRUE.equals(request.getPreviewOnly())) {
                return discountDetectionService.previewOptimalCombination(context);
            } else {
                return discountDetectionService.calculateOptimalCombination(context);
            }
            
        } catch (Exception e) {
            log.error("计算优惠时发生异常", e);
            
            // 返回失败结果
            DiscountCombinationResult failureResult = new DiscountCombinationResult();
            failureResult.setOriginalAmount(currentAmount);
            failureResult.setFinalAmount(currentAmount);
            failureResult.setTotalDiscountAmount(BigDecimal.ZERO);
            failureResult.setSuccess(false);
            failureResult.setErrorMessage("优惠计算失败: " + e.getMessage());
            return failureResult;
        }
    }
    
    /**
     * 设置使用的优惠信息到结果中
     */
    private void setUsedDiscountInfo(PriceCalculationResult result, DiscountCombinationResult discountResult, PriceCalculationRequest request) {
        if (discountResult.getAppliedDiscounts() == null) {
            return;
        }
        
        for (DiscountResult discountApplied : discountResult.getAppliedDiscounts()) {
            DiscountInfo discountInfo = discountApplied.getDiscountInfo();
            
            if ("COUPON".equals(discountInfo.getProviderType()) && discountInfo.getCouponId() != null) {
                // 构建优惠券信息（这里可能需要重新查询完整信息）
                CouponInfo couponInfo = new CouponInfo();
                couponInfo.setCouponId(discountInfo.getCouponId());
                couponInfo.setCouponName(discountInfo.getDiscountName());
                couponInfo.setActualDiscountAmount(discountApplied.getActualDiscountAmount());
                result.setUsedCoupon(couponInfo);
                
            } else if ("VOUCHER".equals(discountInfo.getProviderType()) && discountInfo.getVoucherCode() != null) {
                // 获取券码信息
                VoucherInfo voucherInfo = voucherService.validateAndGetVoucherInfo(
                    discountInfo.getVoucherCode(), 
                    request.getFaceId(),
                    request.getScenicId()
                );
                if (voucherInfo != null) {
                    voucherInfo.setActualDiscountAmount(discountApplied.getActualDiscountAmount());
                    result.setUsedVoucher(voucherInfo);
                }
            }
        }
    }
    
    /**
     * 标记优惠为已使用（仅在非预览模式下调用）
     */
    private void markDiscountsAsUsed(PriceCalculationResult result, PriceCalculationRequest request) {
        try {
            // 标记券码为已使用
            if (result.getUsedVoucher() != null && result.getUsedVoucher().getVoucherCode() != null) {
                String remark = String.format("价格计算使用 - 订单金额: %s", result.getFinalAmount());
                voucherService.markVoucherAsUsed(result.getUsedVoucher().getVoucherCode(), remark, request.getFaceId());
                log.info("已标记券码为使用: {}", result.getUsedVoucher().getVoucherCode());
            }
            
            // 标记优惠券为已使用
            if (result.getUsedCoupon() != null && result.getUsedCoupon().getCouponId() != null) {
                CouponUseRequest couponUseRequest = new CouponUseRequest();
                couponUseRequest.setCouponId(result.getUsedCoupon().getCouponId());
                couponUseRequest.setUserId(request.getUserId());
                couponUseRequest.setOrderId(request.getOrderId());
                couponUseRequest.setDiscountAmount(result.getUsedCoupon().getActualDiscountAmount());
                couponUseRequest.setScenicId(request.getScenicId() != null ? String.valueOf(request.getScenicId()) : null);

                couponService.useCoupon(couponUseRequest);
                log.info("已标记优惠券为使用: couponId={}, userId={}, orderId={}",
                    result.getUsedCoupon().getCouponId(), request.getUserId(), request.getOrderId());
            }
            
        } catch (Exception e) {
            log.error("标记优惠使用状态时发生异常", e);
            // 不抛出异常，避免影响主流程
        }
    }
}
