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

import com.ycwl.basic.pricing.dto.DiscountDetectionContext;
import com.ycwl.basic.pricing.dto.ProductItem;
import com.ycwl.basic.pricing.dto.VoucherInfo;
import com.ycwl.basic.pricing.entity.PriceVoucherBatchConfig;
import com.ycwl.basic.pricing.entity.PriceVoucherCode;
import com.ycwl.basic.pricing.enums.VoucherCodeStatus;
import com.ycwl.basic.pricing.enums.VoucherDiscountType;
import com.ycwl.basic.pricing.mapper.PriceVoucherBatchConfigMapper;
import com.ycwl.basic.pricing.mapper.PriceVoucherCodeMapper;
import com.ycwl.basic.pricing.service.IVoucherService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

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

/**
 * 券码服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class VoucherServiceImpl implements IVoucherService {
    
    private final PriceVoucherCodeMapper voucherCodeMapper;
    private final PriceVoucherBatchConfigMapper voucherBatchConfigMapper;
    
    @Override
    public VoucherInfo validateAndGetVoucherInfo(String voucherCode, Long faceId, Long scenicId) {
        if (!StringUtils.hasText(voucherCode)) {
            return null;
        }
        
        // 查询券码信息
        PriceVoucherCode voucherCodeEntity = voucherCodeMapper.selectByCode(voucherCode);
        if (voucherCodeEntity == null || voucherCodeEntity.getDeleted() == 1) {
            return null;
        }
        
        // 查询批次信息
        PriceVoucherBatchConfig batchConfig = voucherBatchConfigMapper.selectById(voucherCodeEntity.getBatchId());
        if (batchConfig == null || batchConfig.getDeleted() == 1 || batchConfig.getStatus() == 0) {
            return null;
        }
        
        // 验证景区匹配
        if (scenicId != null && !scenicId.equals(voucherCodeEntity.getScenicId())) {
            return null;
        }
        
        VoucherInfo voucherInfo = buildVoucherInfo(voucherCodeEntity, batchConfig);
        
        // 检查券码状态和可用性
        if (VoucherCodeStatus.UNCLAIMED.getCode().equals(voucherCodeEntity.getStatus())) {
            // 未领取状态，检查是否可以领取
            if (faceId != null && canClaimVoucher(faceId, voucherCodeEntity.getScenicId())) {
                voucherInfo.setAvailable(true);
            } else {
                voucherInfo.setAvailable(false);
                voucherInfo.setUnavailableReason("您已在该景区领取过券码");
            }
        } else if (VoucherCodeStatus.CLAIMED_UNUSED.getCode().equals(voucherCodeEntity.getStatus())) {
            // 已领取未使用，检查是否为当前用户
            if (faceId != null && faceId.equals(voucherCodeEntity.getFaceId())) {
                voucherInfo.setAvailable(true);
            } else {
                voucherInfo.setAvailable(false);
                voucherInfo.setUnavailableReason("券码已被其他用户领取");
            }
        } else {
            // 已使用
            voucherInfo.setAvailable(false);
            voucherInfo.setUnavailableReason("券码已使用");
        }
        
        return voucherInfo;
    }
    
    @Override
    public List<VoucherInfo> getAvailableVouchers(Long faceId, Long scenicId) {
        if (faceId == null || scenicId == null) {
            return new ArrayList<>();
        }
        
        List<PriceVoucherCode> voucherCodes = voucherCodeMapper.selectAvailableVouchersByFaceIdAndScenicId(faceId, scenicId);
        List<VoucherInfo> voucherInfos = new ArrayList<>();
        
        for (PriceVoucherCode voucherCode : voucherCodes) {
            PriceVoucherBatchConfig batchConfig = voucherBatchConfigMapper.selectById(voucherCode.getBatchId());
            if (batchConfig != null && batchConfig.getDeleted() == 0 && batchConfig.getStatus() == 1) {
                VoucherInfo voucherInfo = buildVoucherInfo(voucherCode, batchConfig);
                voucherInfo.setAvailable(true);
                voucherInfos.add(voucherInfo);
            }
        }
        
        return voucherInfos;
    }
    
    @Override
    public void markVoucherAsUsed(String voucherCode, String remark) {
        if (!StringUtils.hasText(voucherCode)) {
            return;
        }
        
        int result = voucherCodeMapper.useVoucher(voucherCode, LocalDateTime.now(), remark);
        if (result > 0) {
            // 更新批次统计
            PriceVoucherCode voucherCodeEntity = voucherCodeMapper.selectByCode(voucherCode);
            if (voucherCodeEntity != null) {
                voucherBatchConfigMapper.updateUsedCount(voucherCodeEntity.getBatchId(), 1);
            }
            log.info("券码已标记为使用: {}", voucherCode);
        }
    }
    
    @Override
    public boolean canClaimVoucher(Long faceId, Long scenicId) {
        if (faceId == null || scenicId == null) {
            return false;
        }
        
        Integer count = voucherCodeMapper.countByFaceIdAndScenicId(faceId, scenicId);
        return count == 0;
    }
    
    /**
     * 获取该faceId在scenicId下的券码详情列表
     * @param faceId 用户面部ID
     * @param scenicId 景区ID
     * @return 券码详情列表，包含所有状态的券码（已领取未使用、已使用等），如果没有券码则返回空列表
     */
    public List<VoucherInfo> getVoucherDetails(Long faceId, Long scenicId) {
        if (faceId == null || scenicId == null) {
            return new ArrayList<>();
        }
        
        List<PriceVoucherCode> voucherCodes = voucherCodeMapper.selectUserVouchers(faceId, scenicId);
        List<VoucherInfo> voucherInfos = new ArrayList<>();
        
        for (PriceVoucherCode voucherCode : voucherCodes) {
            PriceVoucherBatchConfig batchConfig = voucherBatchConfigMapper.selectById(voucherCode.getBatchId());
            if (batchConfig != null && batchConfig.getDeleted() == 0) {
                VoucherInfo voucherInfo = buildVoucherInfo(voucherCode, batchConfig);
                
                // 设置可用性状态
                VoucherCodeStatus statusEnum = VoucherCodeStatus.getByCode(voucherCode.getStatus());
                if (statusEnum != null) {
                    switch (statusEnum) {
                        case CLAIMED_UNUSED:
                            voucherInfo.setAvailable(true);
                            break;
                        case USED:
                            voucherInfo.setAvailable(false);
                            voucherInfo.setUnavailableReason("券码已使用");
                            break;
                        case UNCLAIMED:
                            voucherInfo.setAvailable(false);
                            voucherInfo.setUnavailableReason("券码未领取");
                            break;
                        default:
                            voucherInfo.setAvailable(false);
                            voucherInfo.setUnavailableReason("券码状态异常");
                    }
                } else {
                    voucherInfo.setAvailable(false);
                    voucherInfo.setUnavailableReason("券码状态未知");
                }
                
                voucherInfos.add(voucherInfo);
            }
        }
        
        return voucherInfos;
    }
    
    @Override
    public BigDecimal calculateVoucherDiscount(VoucherInfo voucherInfo, DiscountDetectionContext context) {
        if (voucherInfo == null || !Boolean.TRUE.equals(voucherInfo.getAvailable()) || 
            context.getProducts() == null || context.getProducts().isEmpty()) {
            return BigDecimal.ZERO;
        }
        
        VoucherDiscountType discountType = voucherInfo.getDiscountType();
        BigDecimal discountValue = voucherInfo.getDiscountValue();
        
        if (discountType == null) {
            return BigDecimal.ZERO;
        }
        
        return switch (discountType) {
            case FREE_ALL -> {
                // 全场免费，返回当前总金额
                yield context.getCurrentAmount() != null ? context.getCurrentAmount() : BigDecimal.ZERO;
            }
            case REDUCE_PRICE -> {
                // 商品降价，每个商品减免固定金额
                if (discountValue == null || discountValue.compareTo(BigDecimal.ZERO) <= 0) {
                    yield BigDecimal.ZERO;
                }
                BigDecimal totalDiscount = BigDecimal.ZERO;
                for (ProductItem product : context.getProducts()) {
                    BigDecimal productDiscount = discountValue.multiply(BigDecimal.valueOf(product.getQuantity()));
                    totalDiscount = totalDiscount.add(productDiscount);
                }
                yield totalDiscount;
            }
            case DISCOUNT -> {
                // 商品打折，按百分比计算
                if (discountValue == null || discountValue.compareTo(BigDecimal.ZERO) <= 0 || 
                    discountValue.compareTo(BigDecimal.valueOf(100)) >= 0) {
                    yield BigDecimal.ZERO;
                }
                BigDecimal currentAmount = context.getCurrentAmount() != null ? context.getCurrentAmount() : BigDecimal.ZERO;
                BigDecimal discountRate = discountValue.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP);
                yield currentAmount.multiply(discountRate).setScale(2, RoundingMode.HALF_UP);
            }
        };
    }
    
    @Override
    public VoucherInfo getBestVoucher(Long faceId, Long scenicId, DiscountDetectionContext context) {
        List<VoucherInfo> availableVouchers = getAvailableVouchers(faceId, scenicId);
        if (availableVouchers.isEmpty()) {
            return null;
        }
        
        // 计算每个券码的优惠金额，选择最优的
        VoucherInfo bestVoucher = null;
        BigDecimal maxDiscount = BigDecimal.ZERO;
        
        for (VoucherInfo voucher : availableVouchers) {
            BigDecimal discount = calculateVoucherDiscount(voucher, context);
            voucher.setActualDiscountAmount(discount);
            
            if (discount.compareTo(maxDiscount) > 0) {
                maxDiscount = discount;
                bestVoucher = voucher;
            }
        }
        
        return bestVoucher;
    }
    
    /**
     * 构建券码信息DTO
     */
    private VoucherInfo buildVoucherInfo(PriceVoucherCode voucherCode, PriceVoucherBatchConfig batchConfig) {
        VoucherInfo voucherInfo = new VoucherInfo();
        voucherInfo.setVoucherId(voucherCode.getId());
        voucherInfo.setVoucherCode(voucherCode.getCode());
        voucherInfo.setBatchId(batchConfig.getId());
        voucherInfo.setBatchName(batchConfig.getBatchName());
        voucherInfo.setScenicId(voucherCode.getScenicId());
        voucherInfo.setBrokerId(batchConfig.getBrokerId());
        voucherInfo.setDiscountType(VoucherDiscountType.getByCode(batchConfig.getDiscountType()));
        voucherInfo.setDiscountValue(batchConfig.getDiscountValue());
        voucherInfo.setStatus(voucherCode.getStatus());
        voucherInfo.setClaimedTime(voucherCode.getClaimedTime());
        voucherInfo.setUsedTime(voucherCode.getUsedTime());
        
        return voucherInfo;
    }
}