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

import com.ycwl.basic.pricing.dto.BundleDiscountInfo;
import com.ycwl.basic.pricing.dto.DiscountDetectionContext;
import com.ycwl.basic.pricing.dto.ProductItem;
import com.ycwl.basic.pricing.enums.ProductType;
import com.ycwl.basic.pricing.service.IBundleDiscountService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 打包购买优惠服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class BundleDiscountServiceImpl implements IBundleDiscountService {

    @Override
    public List<BundleDiscountInfo> detectAvailableBundleDiscounts(DiscountDetectionContext context) {
        List<BundleDiscountInfo> bundleDiscounts = new ArrayList<>();

        try {
            if (context.getProducts() == null || context.getProducts().isEmpty()) {
                log.debug("商品列表为空，无法检测打包优惠");
                return bundleDiscounts;
            }

            // 获取所有可能的打包优惠规则
            List<BundleDiscountInfo> allRules = getBundleDiscountRules(context.getProducts(), context.getScenicId());

            for (BundleDiscountInfo rule : allRules) {
                if (isBundleDiscountValid(rule, context)) {
                    // 计算实际优惠金额
                    BigDecimal discountAmount = calculateBundleDiscount(rule, context.getProducts());
                    if (discountAmount.compareTo(BigDecimal.ZERO) > 0) {
                        rule.setActualDiscountAmount(discountAmount);
                        bundleDiscounts.add(rule);
                    }
                }
            }

            log.debug("检测到 {} 个可用的打包优惠", bundleDiscounts.size());

        } catch (Exception e) {
            log.error("检测打包优惠失败", e);
        }

        return bundleDiscounts;
    }

    @Override
    public BigDecimal calculateBundleDiscount(BundleDiscountInfo bundleDiscount, List<ProductItem> products) {
        try {
            if (bundleDiscount == null || products == null || products.isEmpty()) {
                return BigDecimal.ZERO;
            }

            // 计算符合条件的商品总金额
            BigDecimal totalAmount = products.stream()
                    .map(ProductItem::getSubtotal)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            // 计算符合条件的商品总数量
            int totalQuantity = products.stream()
                    .mapToInt(ProductItem::getQuantity)
                    .sum();

            // 检查是否满足最低条件
            if (!isEligibleForBundle(products, bundleDiscount.getMinQuantity(), bundleDiscount.getMinAmount())) {
                return BigDecimal.ZERO;
            }

            // 根据优惠类型计算折扣
            return switch (bundleDiscount.getDiscountType()) {
                case "FIXED_DISCOUNT" -> {
                    // 固定减免金额
                    BigDecimal discount = bundleDiscount.getDiscountValue();
                    yield discount.min(totalAmount); // 优惠不能超过总金额
                }
                case "PERCENTAGE_DISCOUNT" -> {
                    // 百分比折扣
                    BigDecimal discountRate = BigDecimal.ONE.subtract(bundleDiscount.getDiscountValue());
                    yield totalAmount.multiply(discountRate).setScale(2, RoundingMode.HALF_UP);
                }
                case "FIXED_PRICE" -> {
                    // 固定价格
                    BigDecimal fixedPrice = bundleDiscount.getDiscountValue();
                    BigDecimal discount = totalAmount.subtract(fixedPrice);
                    yield discount.max(BigDecimal.ZERO); // 固定价格不能高于原价
                }
                default -> {
                    log.warn("未知的打包优惠类型: {}", bundleDiscount.getDiscountType());
                    yield BigDecimal.ZERO;
                }
            };

        } catch (Exception e) {
            log.error("计算打包优惠金额失败", e);
            return BigDecimal.ZERO;
        }
    }

    @Override
    public boolean isEligibleForBundle(List<ProductItem> products, Integer minQuantity, BigDecimal minAmount) {
        if (products == null || products.isEmpty()) {
            return false;
        }

        // 检查数量要求
        if (minQuantity != null && minQuantity > 0) {
            int totalQuantity = products.stream()
                    .mapToInt(ProductItem::getQuantity)
                    .sum();
            if (totalQuantity < minQuantity) {
                return false;
            }
        }

        // 检查金额要求
        if (minAmount != null && minAmount.compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal totalAmount = products.stream()
                    .map(ProductItem::getSubtotal)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            if (totalAmount.compareTo(minAmount) < 0) {
                return false;
            }
        }

        return true;
    }

    @Override
    public List<BundleDiscountInfo> getBundleDiscountRules(List<ProductItem> products, Long scenicId) {
        List<BundleDiscountInfo> rules = new ArrayList<>();

        try {
            // 这里实现获取打包优惠规则的逻辑
            // 可以从数据库加载配置，或者使用硬编码的规则

            // 示例规则1：多商品打包优惠
            if (hasMultipleProductTypes(products)) {
                BundleDiscountInfo multiProductBundle = createMultiProductBundleRule();
                rules.add(multiProductBundle);
            }

            // 示例规则2：大批量优惠
            if (hasLargeQuantity(products)) {
                BundleDiscountInfo bulkBundle = createBulkDiscountRule();
                rules.add(bulkBundle);
            }

            // 示例规则3：特定商品组合优惠
            if (hasSpecificCombination(products)) {
                BundleDiscountInfo combinationBundle = createCombinationDiscountRule();
                rules.add(combinationBundle);
            }

            log.debug("为 {} 个商品获取到 {} 个打包优惠规则", products.size(), rules.size());

        } catch (Exception e) {
            log.error("获取打包优惠规则失败", e);
        }

        return rules;
    }

    @Override
    public boolean isBundleDiscountValid(BundleDiscountInfo bundleDiscount, DiscountDetectionContext context) {
        try {
            if (bundleDiscount == null) {
                return false;
            }

            // 检查是否满足基本条件
            if (!isEligibleForBundle(context.getProducts(), bundleDiscount.getMinQuantity(), bundleDiscount.getMinAmount())) {
                return false;
            }

            // 可以添加更多的验证逻辑，比如时间范围、用户类型等
            // TODO: 根据实际业务需求实现更多验证逻辑

            return true;

        } catch (Exception e) {
            log.error("验证打包优惠有效性失败", e);
            return false;
        }
    }

    @Override
    public BundleDiscountInfo getBestBundleDiscount(List<ProductItem> products, Long scenicId) {
        try {
            List<BundleDiscountInfo> availableRules = getBundleDiscountRules(products, scenicId);

            return availableRules.stream()
                    .filter(rule -> {
                        BigDecimal discount = calculateBundleDiscount(rule, products);
                        rule.setActualDiscountAmount(discount);
                        return discount.compareTo(BigDecimal.ZERO) > 0;
                    })
                    .max(Comparator.comparing(BundleDiscountInfo::getActualDiscountAmount))
                    .orElse(null);

        } catch (Exception e) {
            log.error("获取最优打包优惠失败", e);
            return null;
        }
    }

    /**
     * 检查是否有多种商品类型
     */
    private boolean hasMultipleProductTypes(List<ProductItem> products) {
        Set<ProductType> productTypes = products.stream()
                .map(ProductItem::getProductType)
                .collect(Collectors.toSet());
        return productTypes.size() >= 2;
    }

    /**
     * 检查是否有大批量商品
     */
    private boolean hasLargeQuantity(List<ProductItem> products) {
        int totalQuantity = products.stream()
                .mapToInt(ProductItem::getQuantity)
                .sum();
        return totalQuantity >= 10; // 示例：10件以上
    }

    /**
     * 检查是否有特定商品组合
     */
    private boolean hasSpecificCombination(List<ProductItem> products) {
        Set<ProductType> productTypes = products.stream()
                .map(ProductItem::getProductType)
                .collect(Collectors.toSet());

        // 示例：照片+视频组合
        return productTypes.contains(ProductType.PHOTO_SET) &&
               productTypes.contains(ProductType.VLOG_VIDEO);
    }

    /**
     * 创建多商品打包规则
     */
    private BundleDiscountInfo createMultiProductBundleRule() {
        BundleDiscountInfo bundle = new BundleDiscountInfo();
        bundle.setBundleConfigId(1L);
        bundle.setBundleName("多商品组合优惠");
        bundle.setBundleDescription("购买不同类型商品享受组合优惠");
        bundle.setDiscountType("PERCENTAGE_DISCOUNT");
        bundle.setDiscountValue(new BigDecimal("0.9")); // 9折
        bundle.setMinQuantity(2);
        bundle.setMinAmount(new BigDecimal("100"));
        bundle.setCanUseWithCoupon(true);
        bundle.setCanUseWithVoucher(true);
        bundle.setCanUseWithOnePrice(false); // 不能与一口价叠加
        return bundle;
    }

    /**
     * 创建大批量优惠规则
     */
    private BundleDiscountInfo createBulkDiscountRule() {
        BundleDiscountInfo bundle = new BundleDiscountInfo();
        bundle.setBundleConfigId(2L);
        bundle.setBundleName("大批量购买优惠");
        bundle.setBundleDescription("购买数量达到要求享受批量优惠");
        bundle.setDiscountType("FIXED_DISCOUNT");
        bundle.setDiscountValue(new BigDecimal("50")); // 减免50元
        bundle.setMinQuantity(10);
        bundle.setMinAmount(new BigDecimal("500"));
        bundle.setCanUseWithCoupon(true);
        bundle.setCanUseWithVoucher(true);
        bundle.setCanUseWithOnePrice(false);
        return bundle;
    }

    /**
     * 创建特定组合优惠规则
     */
    private BundleDiscountInfo createCombinationDiscountRule() {
        BundleDiscountInfo bundle = new BundleDiscountInfo();
        bundle.setBundleConfigId(3L);
        bundle.setBundleName("照片+视频套餐");
        bundle.setBundleDescription("同时购买照片和视频享受套餐优惠");
        bundle.setDiscountType("FIXED_PRICE");
        bundle.setDiscountValue(new BigDecimal("199")); // 套餐价199元
        bundle.setMinQuantity(2);
        bundle.setMinAmount(new BigDecimal("200"));
        bundle.setCanUseWithCoupon(false);
        bundle.setCanUseWithVoucher(false);
        bundle.setCanUseWithOnePrice(false);
        return bundle;
    }
}