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.enums.VoucherDiscountType;
import com.ycwl.basic.pricing.service.IDiscountProvider;
import com.ycwl.basic.pricing.service.IPriceBundleService;
import com.ycwl.basic.pricing.service.IProductConfigService;
import com.ycwl.basic.pricing.service.IVoucherService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 券码折扣提供者
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class VoucherDiscountProvider implements IDiscountProvider {
    
    private final IVoucherService voucherService;
    private final IProductConfigService productConfigService;
    private final IPriceBundleService bundleService;
    
    @Override
    public String getProviderType() {
        return "VOUCHER";
    }
    
    @Override
    public int getPriority() {
        return 80; // 券码优先级第三，仅次于一口价和打包购买
    }
    
    @Override
    public List<DiscountInfo> detectAvailableDiscounts(DiscountDetectionContext context) {
        List<DiscountInfo> discounts = new ArrayList<>();
        
        if (context.getFaceId() == null || context.getScenicId() == null) {
            return discounts;
        }
        
        // 检查商品配置和打包配置是否允许使用券码
        if (!checkCanUseVoucher(context)) {
            log.debug("商品配置不允许使用券码，跳过券码检测");
            return discounts;
        }
        
        try {
            VoucherInfo voucherInfo = null;
            
            // 优先检查用户主动输入的券码
            if (StringUtils.hasText(context.getVoucherCode())) {
                voucherInfo = voucherService.validateAndGetVoucherInfo(
                    context.getVoucherCode(), 
                    context.getFaceId(), 
                    context.getScenicId()
                );
            } 
            // 如果没有输入券码且允许自动使用，则查找最优券码
            else if (Boolean.TRUE.equals(context.getAutoUseVoucher())) {
                voucherInfo = voucherService.getBestVoucher(
                    context.getFaceId(), 
                    context.getScenicId(), 
                    context
                );
            }
            
            if (voucherInfo != null && Boolean.TRUE.equals(voucherInfo.getAvailable())) {
                // 计算券码优惠金额
                BigDecimal discountAmount = voucherService.calculateVoucherDiscount(voucherInfo, context);
                
                if (discountAmount.compareTo(BigDecimal.ZERO) > 0) {
                    DiscountInfo discountInfo = new DiscountInfo();
                    discountInfo.setDiscountId(voucherInfo.getVoucherId());
                    discountInfo.setDiscountType("VOUCHER");
                    discountInfo.setDiscountName("券码优惠");
                    discountInfo.setDiscountDescription(buildDiscountDescription(voucherInfo));
                    discountInfo.setDiscountAmount(discountAmount);
                    discountInfo.setProviderType(getProviderType());
                    discountInfo.setPriority(getPriority());
                    discountInfo.setStackable(isStackable(voucherInfo)); // 只有全场免费不可叠加
                    discountInfo.setVoucherCode(voucherInfo.getVoucherCode());
                    
                    discounts.add(discountInfo);
                }
            }
        } catch (Exception e) {
            log.warn("检测券码优惠时发生异常", e);
        }
        
        return discounts;
    }
    
    @Override
    public DiscountResult applyDiscount(DiscountInfo discountInfo, DiscountDetectionContext context) {
        DiscountResult result = new DiscountResult();
        result.setDiscountInfo(discountInfo);
        
        try {
            String voucherCode = discountInfo.getVoucherCode();
            if (!StringUtils.hasText(voucherCode)) {
                result.setSuccess(false);
                result.setFailureReason("券码信息丢失");
                return result;
            }
            
            // 重新验证券码，包括重复使用权限验证
            VoucherInfo voucherInfo = voucherService.validateAndGetVoucherInfo(
                voucherCode, 
                context.getFaceId(), 
                context.getScenicId()
            );
            
            if (voucherInfo == null) {
                result.setSuccess(false);
                result.setFailureReason("券码不存在或已失效");
                return result;
            }
            
            if (!Boolean.TRUE.equals(voucherInfo.getAvailable())) {
                result.setSuccess(false);
                result.setFailureReason(voucherInfo.getUnavailableReason() != null ? 
                    voucherInfo.getUnavailableReason() : "券码不可用");
                return result;
            }
            
            // 计算实际优惠金额
            BigDecimal actualDiscount = voucherService.calculateVoucherDiscount(voucherInfo, context);
            if (actualDiscount.compareTo(BigDecimal.ZERO) <= 0) {
                result.setSuccess(false);
                result.setFailureReason("券码无法应用到当前商品");
                return result;
            }
            
            BigDecimal finalAmount;
            
            // 对于全场免费券码，最终金额为0
            if (voucherInfo.getDiscountType() == VoucherDiscountType.FREE_ALL) {
                finalAmount = BigDecimal.ZERO;
                actualDiscount = context.getCurrentAmount();
            } else {
                finalAmount = context.getCurrentAmount().subtract(actualDiscount);
                if (finalAmount.compareTo(BigDecimal.ZERO) < 0) {
                    finalAmount = BigDecimal.ZERO;
                    actualDiscount = context.getCurrentAmount();
                }
            }
            
            result.setActualDiscountAmount(actualDiscount);
            result.setFinalAmount(finalAmount);
            result.setSuccess(true);
            
            // 显示剩余使用次数信息，处理无限次使用的情况
            String remainingInfo = voucherInfo.getRemainingUseCount() != null ? 
                voucherInfo.getRemainingUseCount().toString() : "无限次";
            log.info("成功应用券码: {}, 优惠金额: {}, 剩余使用次数: {}", 
                voucherCode, actualDiscount, remainingInfo);
            
        } catch (Exception e) {
            log.error("应用券码失败: " + discountInfo.getVoucherCode(), e);
            result.setSuccess(false);
            result.setFailureReason("券码应用失败: " + e.getMessage());
        }
        
        return result;
    }
    
    @Override
    public boolean canApply(DiscountInfo discountInfo, DiscountDetectionContext context) {
        return "VOUCHER".equals(discountInfo.getDiscountType()) &&
               context.getFaceId() != null &&
               context.getScenicId() != null &&
               StringUtils.hasText(discountInfo.getVoucherCode()) &&
               checkCanUseVoucher(context);
    }
    
    /**
     * 构建优惠描述
     */
    private String buildDiscountDescription(VoucherInfo voucherInfo) {
        if (voucherInfo.getDiscountType() == null) {
            return "券码优惠";
        }
        
        return String.format("券码 %s - %s", 
            voucherInfo.getVoucherCode(), 
            voucherInfo.getDiscountType().getName());
    }
    
    /**
     * 判断是否可以与其他优惠叠加
     */
    private boolean isStackable(VoucherInfo voucherInfo) {
        // 全场免费券码不可与其他优惠叠加
        return voucherInfo.getDiscountType() != VoucherDiscountType.FREE_ALL;
    }
    
    /**
     * 检查商品配置和打包配置是否允许使用券码
     */
    private boolean checkCanUseVoucher(DiscountDetectionContext context) {
        if (context.getProducts() == null || context.getProducts().isEmpty()) {
            return true; // 如果没有商品信息，默认允许
        }
        
        try {
            // 检查是否使用了打包购买
            BigDecimal bundlePrice = bundleService.getBundlePrice(context.getProducts());
            if (bundlePrice != null) {
                // 如果使用了打包购买，检查打包配置的券码使用开关
                PriceBundleConfig bundleConfig = bundleService.getBundleConfig(context.getProducts());
                if (bundleConfig != null) {
                    boolean canUseVoucher = Boolean.TRUE.equals(bundleConfig.getCanUseVoucher());
                    log.debug("打包配置券码开关检查: bundleId={}, canUseVoucher={}", bundleConfig.getId(), canUseVoucher);
                    return canUseVoucher;
                }
            }
            
            // 检查单个商品的券码使用开关（使用景区维度配置）
            for (ProductItem product : context.getProducts()) {
                String productId = product.getProductId() != null ? product.getProductId() : "default";

                try {
                    PriceProductConfig productConfig = productConfigService.getProductConfig(
                        product.getProductType().getCode(), productId, context.getScenicId());

                    if (productConfig != null) {
                        if (!Boolean.TRUE.equals(productConfig.getCanUseVoucher())) {
                            log.info("商品配置不允许使用券码: productType={}, productId={}, scenicId={}",
                                product.getProductType().getCode(), productId, context.getScenicId());
                            return false;
                        }
                    }
                } catch (Exception e) {
                    // 如果获取具体商品配置失败，尝试获取default配置
                    try {
                        PriceProductConfig defaultConfig = productConfigService.getProductConfig(
                            product.getProductType().getCode(), "default", context.getScenicId());

                        if (defaultConfig != null) {
                            if (!Boolean.TRUE.equals(defaultConfig.getCanUseVoucher())) {
                                log.debug("商品默认配置不允许使用券码: productType={}, scenicId={}",
                                    product.getProductType().getCode(), context.getScenicId());
                                return false;
                            }
                        }
                    } catch (Exception ex) {
                        log.warn("获取商品配置失败，默认允许使用券码: productType={}, productId={}, scenicId={}",
                            product.getProductType().getCode(), productId, context.getScenicId());
                    }
                }
            }
            
        } catch (Exception e) {
            log.error("检查券码使用开关时发生异常，默认允许使用", e);
        }
        
        return true; // 默认允许使用券码
    }
}