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

import com.ycwl.basic.pricing.dto.*;
import com.ycwl.basic.pricing.service.IDiscountDetectionService;
import com.ycwl.basic.pricing.service.IDiscountProvider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 优惠检测服务实现
 */
@Slf4j
@Service
public class DiscountDetectionServiceImpl implements IDiscountDetectionService {

    private final ObjectProvider<IDiscountProvider> discountProviderProvider;
    private final List<IDiscountProvider> discountProviders = new ArrayList<>();
    private final Object providerInitLock = new Object();
    private volatile boolean providersInitialized;

    @Autowired
    public DiscountDetectionServiceImpl(ObjectProvider<IDiscountProvider> discountProviderProvider) {
        this.discountProviderProvider = discountProviderProvider;
    }

    @Override
    public List<DiscountInfo> detectAllAvailableDiscounts(DiscountDetectionContext context) {
        initializeProvidersIfNecessary();
        List<DiscountInfo> allDiscounts = new ArrayList<>();

        for (IDiscountProvider provider : discountProviders) {
            try {
                List<DiscountInfo> providerDiscounts = provider.detectAvailableDiscounts(context);
                if (providerDiscounts != null && !providerDiscounts.isEmpty()) {
                    allDiscounts.addAll(providerDiscounts);
                    log.debug("提供者 {} 检测到 {} 个优惠", provider.getProviderType(), providerDiscounts.size());
                }
            } catch (Exception e) {
                log.error("优惠提供者 {} 检测失败", provider.getProviderType(), e);
            }
        }

        // 按优先级排序
        allDiscounts.sort(Comparator.comparing(DiscountInfo::getPriority).reversed());

        return allDiscounts;
    }

    @Override
    public DiscountCombinationResult calculateOptimalCombination(DiscountDetectionContext context) {
        DiscountCombinationResult result = new DiscountCombinationResult();
        result.setOriginalAmount(context.getCurrentAmount());

        try {
            List<DiscountInfo> availableDiscounts = detectAllAvailableDiscounts(context);
            result.setAvailableDiscounts(availableDiscounts);

            if (availableDiscounts.isEmpty()) {
                result.setFinalAmount(context.getCurrentAmount());
                result.setTotalDiscountAmount(BigDecimal.ZERO);
                result.setAppliedDiscounts(new ArrayList<>());
                result.setDiscountDetails(new ArrayList<>());
                result.setSuccess(true);
                return result;
            }

            List<DiscountResult> appliedDiscounts = new ArrayList<>();
            List<DiscountDetail> discountDetails = new ArrayList<>();
            BigDecimal currentAmount = context.getCurrentAmount();

            // 按优先级应用优惠
            for (DiscountInfo discountInfo : availableDiscounts) {
                IDiscountProvider provider = findProvider(discountInfo.getProviderType());
                if (provider == null || !provider.canApply(discountInfo, context)) {
                    continue;
                }

                // 更新上下文中的当前金额
                context.setCurrentAmount(currentAmount);

                DiscountResult discountResult = provider.applyDiscount(discountInfo, context);
                if (Boolean.TRUE.equals(discountResult.getSuccess())) {
                    appliedDiscounts.add(discountResult);

                    // 创建显示用的优惠详情
                    DiscountDetail detail = createDiscountDetail(discountResult);
                    if (detail != null) {
                        discountDetails.add(detail);
                    }

                    // 更新当前金额
                    currentAmount = discountResult.getFinalAmount();

                    log.info("成功应用优惠: {} - {}, 优惠金额: {}",
                        discountInfo.getProviderType(),
                        discountInfo.getDiscountName(),
                        discountResult.getActualDiscountAmount());

                    // 如果是不可叠加的优惠（如全场免费），则停止应用其他优惠
                    if (!Boolean.TRUE.equals(discountInfo.getStackable())) {
                        log.info("遇到不可叠加优惠，停止应用其他优惠: {}", discountInfo.getDiscountName());
                        break;
                    }
                } else {
                    log.warn("优惠应用失败: {} - {}, 原因: {}",
                        discountInfo.getProviderType(),
                        discountInfo.getDiscountName(),
                        discountResult.getFailureReason());
                }
            }

            // 计算总优惠金额
            BigDecimal totalDiscountAmount = appliedDiscounts.stream()
                .map(DiscountResult::getActualDiscountAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

            // 按显示顺序排序折扣详情
            discountDetails.sort(Comparator.comparing(DiscountDetail::getSortOrder));

            result.setFinalAmount(currentAmount);
            result.setTotalDiscountAmount(totalDiscountAmount);
            result.setAppliedDiscounts(appliedDiscounts);
            result.setDiscountDetails(discountDetails);
            result.setSuccess(true);

        } catch (Exception e) {
            log.error("计算最优优惠组合失败", e);
            result.setSuccess(false);
            result.setErrorMessage("优惠计算失败: " + e.getMessage());
            result.setFinalAmount(context.getCurrentAmount());
            result.setTotalDiscountAmount(BigDecimal.ZERO);
        }

        return result;
    }

    @Override
    public DiscountCombinationResult previewOptimalCombination(DiscountDetectionContext context) {
        // 预览模式与正常计算相同，但不会实际标记优惠为已使用
        return calculateOptimalCombination(context);
    }

    @Override
    public void registerProvider(IDiscountProvider provider) {
        if (provider == null) {
            return;
        }
        synchronized (providerInitLock) {
            initializeProvidersIfNecessary();
            if (!discountProviders.contains(provider)) {
                discountProviders.add(provider);
                discountProviders.sort(Comparator.comparing(IDiscountProvider::getPriority).reversed());
                log.info("注册新的优惠提供者: {}", provider.getProviderType());
            }
        }
    }

    @Override
    public List<IDiscountProvider> getAllProviders() {
        initializeProvidersIfNecessary();
        return new ArrayList<>(discountProviders);
    }

    /**
     * 查找指定类型的优惠提供者
     */
    private IDiscountProvider findProvider(String providerType) {
        initializeProvidersIfNecessary();
        return discountProviders.stream()
            .filter(provider -> providerType.equals(provider.getProviderType()))
            .findFirst()
            .orElse(null);
    }

    /**
     * 创建显示用的优惠详情
     */
    private DiscountDetail createDiscountDetail(DiscountResult discountResult) {
        DiscountInfo discountInfo = discountResult.getDiscountInfo();
        String providerType = discountInfo.getProviderType();

        return switch (providerType) {
            case "VOUCHER" -> DiscountDetail.createVoucherDiscount(
                discountInfo.getVoucherCode(),
                discountInfo.getDiscountDescription(),
                discountResult.getActualDiscountAmount()
            );
            case "COUPON" -> DiscountDetail.createCouponDiscount(
                discountInfo.getDiscountName(),
                discountResult.getActualDiscountAmount()
            );
            default -> {
                // 其他类型的优惠，创建通用的折扣详情
                DiscountDetail detail = new DiscountDetail();
                detail.setDiscountType(providerType);
                detail.setDiscountName(discountInfo.getDiscountName());
                detail.setDiscountAmount(discountResult.getActualDiscountAmount());
                detail.setDescription(discountInfo.getDiscountDescription());
                detail.setSortOrder(10); // 默认排序
                yield detail;
            }
        };
    }

    private void initializeProvidersIfNecessary() {
        if (providersInitialized) {
            return;
        }
        synchronized (providerInitLock) {
            if (providersInitialized) {
                return;
            }
            discountProviders.clear();
            discountProviderProvider.stream().forEach(discountProviders::add);
            discountProviders.sort(Comparator.comparing(IDiscountProvider::getPriority).reversed());
            log.info("注册了 {} 个优惠提供者: {}",
                discountProviders.size(),
                discountProviders.stream().map(IDiscountProvider::getProviderType).collect(Collectors.toList()));
            providersInitialized = true;
        }
    }
}
