package com.gxwebsoft.shop.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.gxwebsoft.shop.entity.ShopUserCoupon;
import com.gxwebsoft.shop.entity.ShopCoupon;
import com.gxwebsoft.shop.entity.ShopCouponApplyItem;
import com.gxwebsoft.shop.service.CouponStatusService;
import com.gxwebsoft.shop.service.ShopUserCouponService;
import com.gxwebsoft.shop.service.ShopCouponService;
import com.gxwebsoft.shop.service.ShopCouponApplyItemService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 优惠券状态管理服务实现
 *
 * @author WebSoft
 * @since 2025-01-15
 */
@Slf4j
@Service
public class CouponStatusServiceImpl implements CouponStatusService {

    @Autowired
    private ShopUserCouponService shopUserCouponService;

    @Autowired
    private ShopCouponService shopCouponService;

    @Autowired
    private ShopCouponApplyItemService shopCouponApplyItemService;

    @Override
    public List<ShopUserCoupon> getAvailableCoupons(Integer userId) {
        List<ShopUserCoupon> allCoupons = getUserCoupons(userId);
        return allCoupons.stream()
                .filter(ShopUserCoupon::isAvailable)
                .collect(Collectors.toList());
    }

    @Override
    public List<ShopUserCoupon> getUsedCoupons(Integer userId) {
        return shopUserCouponService.list(
                new LambdaQueryWrapper<ShopUserCoupon>()
                        .eq(ShopUserCoupon::getUserId, userId)
                        .eq(ShopUserCoupon::getStatus, ShopUserCoupon.STATUS_USED)
                        .orderByDesc(ShopUserCoupon::getUseTime)
        );
    }

    @Override
    public List<ShopUserCoupon> getExpiredCoupons(Integer userId) {
        // 先更新过期状态
        updateExpiredCouponsForUser(userId);

        return shopUserCouponService.list(
                new LambdaQueryWrapper<ShopUserCoupon>()
                        .eq(ShopUserCoupon::getUserId, userId)
                        .eq(ShopUserCoupon::getStatus, ShopUserCoupon.STATUS_EXPIRED)
                        .orderByDesc(ShopUserCoupon::getEndTime)
        );
    }

    @Override
    public CouponStatusResult getUserCouponsGroupByStatus(Integer userId) {
        List<ShopUserCoupon> availableCoupons = getAvailableCoupons(userId);
        List<ShopUserCoupon> usedCoupons = getUsedCoupons(userId);
        List<ShopUserCoupon> expiredCoupons = getExpiredCoupons(userId);

        return new CouponStatusResult(availableCoupons, usedCoupons, expiredCoupons);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean useCoupon(Long userCouponId, Integer orderId, String orderNo) {
        try {
            ShopUserCoupon userCoupon = shopUserCouponService.getById(userCouponId);
            if (userCoupon == null) {
                log.warn("优惠券不存在: {}", userCouponId);
                return false;
            }

            if (!userCoupon.isAvailable()) {
                log.warn("优惠券不可用: {}, 状态: {}", userCouponId, userCoupon.getStatusDesc());
                return false;
            }

            // 标记为已使用
            userCoupon.markAsUsed(orderId, orderNo);

            return shopUserCouponService.updateById(userCoupon);
        } catch (Exception e) {
            log.error("使用优惠券失败: {}", userCouponId, e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean returnCoupon(Integer orderId) {
        try {
            ShopUserCoupon userCoupon = shopUserCouponService.getOne(
                    new LambdaQueryWrapper<ShopUserCoupon>()
                            .eq(ShopUserCoupon::getOrderId, orderId)
                            .eq(ShopUserCoupon::getStatus, ShopUserCoupon.STATUS_USED)
            );

            if (userCoupon == null) {
                log.info("订单没有使用优惠券: {}", orderId);
                return true;
            }

            // 检查是否已过期
            if (userCoupon.isExpired()) {
                log.warn("优惠券已过期，无法退还: {}", userCoupon.getId());
                return false;
            }

            // 恢复为未使用状态
            userCoupon.setStatus(ShopUserCoupon.STATUS_UNUSED);
            userCoupon.setIsUse(0);
            userCoupon.setUseTime(null);
            userCoupon.setOrderId(null);
            userCoupon.setOrderNo(null);

            return shopUserCouponService.updateById(userCoupon);
        } catch (Exception e) {
            log.error("退还优惠券失败, 订单ID: {}", orderId, e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateExpiredCoupons() {
        try {
            // 查询所有未使用且已过期的优惠券
            List<ShopUserCoupon> expiredCoupons = shopUserCouponService.list(
                    new LambdaQueryWrapper<ShopUserCoupon>()
                            .eq(ShopUserCoupon::getStatus, ShopUserCoupon.STATUS_UNUSED)
                            .lt(ShopUserCoupon::getEndTime, LocalDateTime.now())
            );

            if (expiredCoupons.isEmpty()) {
                return 0;
            }

            // 批量更新状态
            List<Long> expiredIds = expiredCoupons.stream()
                    .map(ShopUserCoupon::getId)
                    .collect(Collectors.toList());

            boolean success = shopUserCouponService.update(
                    new LambdaUpdateWrapper<ShopUserCoupon>()
                            .in(ShopUserCoupon::getId, expiredIds)
                            .set(ShopUserCoupon::getStatus, ShopUserCoupon.STATUS_EXPIRED)
                            .set(ShopUserCoupon::getIsExpire, 1)
            );

            int updatedCount = success ? expiredIds.size() : 0;
            log.info("批量更新过期优惠券状态完成，更新数量: {}", updatedCount);
            return updatedCount;
        } catch (Exception e) {
            log.error("批量更新过期优惠券状态失败", e);
            return 0;
        }
    }

    @Override
    public boolean checkAndUpdateCouponStatus(ShopUserCoupon userCoupon) {
        if (userCoupon == null) {
            return false;
        }

        boolean statusChanged = false;

        // 检查是否过期
        if (userCoupon.getStatus() == ShopUserCoupon.STATUS_UNUSED && userCoupon.isExpired()) {
            userCoupon.markAsExpired();
            statusChanged = true;
        }

        // 如果状态发生变化，更新数据库
        if (statusChanged) {
            try {
                shopUserCouponService.updateById(userCoupon);
                log.debug("更新优惠券状态: {} -> {}", userCoupon.getId(), userCoupon.getStatusDesc());
            } catch (Exception e) {
                log.error("更新优惠券状态失败: {}", userCoupon.getId(), e);
                return false;
            }
        }

        return statusChanged;
    }

    @Override
    public CouponValidationResult validateCouponForOrder(Long userCouponId,
                                                          BigDecimal totalAmount,
                                                          List<Integer> goodsIds) {
        try {
            ShopUserCoupon userCoupon = shopUserCouponService.getById(userCouponId);
            if (userCoupon == null) {
                return new CouponValidationResult(false, "优惠券不存在");
            }

            // 检查优惠券状态
            if (!userCoupon.isAvailable()) {
                return new CouponValidationResult(false, "优惠券" + userCoupon.getStatusDesc());
            }

            // 检查最低消费金额
            if (userCoupon.getMinPrice() != null &&
                totalAmount.compareTo(userCoupon.getMinPrice()) < 0) {
                return new CouponValidationResult(false,
                        String.format("订单金额不满足最低消费要求，需满%s元", userCoupon.getMinPrice()));
            }

            // 检查适用范围
            if (!validateApplyRange(userCoupon, goodsIds)) {
                return new CouponValidationResult(false, "优惠券不适用于当前商品");
            }

            // 计算优惠金额
            BigDecimal discountAmount = calculateDiscountAmount(userCoupon, totalAmount);

            return new CouponValidationResult(true, "优惠券可用", discountAmount);
        } catch (Exception e) {
            log.error("验证优惠券失败: {}", userCouponId, e);
            return new CouponValidationResult(false, "验证优惠券时发生错误");
        }
    }

    /**
     * 获取用户所有优惠券
     */
    private List<ShopUserCoupon> getUserCoupons(Integer userId) {
        List<ShopUserCoupon> coupons = shopUserCouponService.list(
                new LambdaQueryWrapper<ShopUserCoupon>()
                        .eq(ShopUserCoupon::getUserId, userId)
                        .orderByAsc(ShopUserCoupon::getEndTime)
        );

        // 检查并更新状态
        coupons.forEach(this::checkAndUpdateCouponStatus);

        return coupons;
    }

    /**
     * 更新指定用户的过期优惠券
     */
    private void updateExpiredCouponsForUser(Integer userId) {
        try {
            shopUserCouponService.update(
                    new LambdaUpdateWrapper<ShopUserCoupon>()
                            .eq(ShopUserCoupon::getUserId, userId)
                            .eq(ShopUserCoupon::getStatus, ShopUserCoupon.STATUS_UNUSED)
                            .lt(ShopUserCoupon::getEndTime, LocalDateTime.now())
                            .set(ShopUserCoupon::getStatus, ShopUserCoupon.STATUS_EXPIRED)
                            .set(ShopUserCoupon::getIsExpire, 1)
            );
        } catch (Exception e) {
            log.error("更新用户过期优惠券失败, userId: {}", userId, e);
        }
    }

    /**
     * 验证优惠券适用范围
     */
    private boolean validateApplyRange(ShopUserCoupon userCoupon, List<Integer> goodsIds) {
        if (userCoupon.getApplyRange() == null || userCoupon.getApplyRange() == ShopUserCoupon.APPLY_ALL) {
            return true; // 全部商品适用
        }

        if (userCoupon.getApplyRange() == ShopUserCoupon.APPLY_GOODS) {
            // 指定商品适用
            try {
                List<ShopCouponApplyItem> applyItems = shopCouponApplyItemService.list(
                        new LambdaQueryWrapper<ShopCouponApplyItem>()
                                .eq(ShopCouponApplyItem::getCouponId, userCoupon.getCouponId())
                                .eq(ShopCouponApplyItem::getType, 1) // 类型1表示商品
                );

                // 如果数据库中还没有 goods_id 字段，暂时使用 pk 字段作为商品ID
                List<Integer> applicableGoodsIds = applyItems.stream()
                        .map(item -> {
                            if (item.getGoodsId() != null) {
                                return item.getGoodsId();
                            } else if (item.getPk() != null) {
                                // 临时方案：使用 pk 字段作为商品ID
                                return item.getPk();
                            }
                            return null;
                        })
                        .filter(goodsId -> goodsId != null)
                        .collect(Collectors.toList());

                return goodsIds.stream().anyMatch(applicableGoodsIds::contains);
            } catch (Exception e) {
                log.warn("查询优惠券适用商品失败，可能是数据库字段不存在: {}", e.getMessage());
                // 如果查询失败，默认返回true（允许使用）
                return true;
            }
        }

        if (userCoupon.getApplyRange() == ShopUserCoupon.APPLY_CATEGORY) {
            // 指定分类适用 - 这里需要根据商品ID查询分类ID，然后验证
            // 暂时返回true，实际项目中需要实现商品分类查询逻辑
            log.debug("分类适用范围验证暂未实现，默认通过");
            return true;
        }

        return true;
    }

    /**
     * 计算优惠金额
     */
    private BigDecimal calculateDiscountAmount(ShopUserCoupon userCoupon, BigDecimal totalAmount) {
        if (userCoupon.getType() == ShopUserCoupon.TYPE_REDUCE) {
            // 满减券
            return userCoupon.getReducePrice();
        } else if (userCoupon.getType() == ShopUserCoupon.TYPE_DISCOUNT) {
            // 折扣券
            BigDecimal discountRate = BigDecimal.valueOf(userCoupon.getDiscount()).divide(BigDecimal.valueOf(100));
            return totalAmount.multiply(BigDecimal.ONE.subtract(discountRate));
        }
        return BigDecimal.ZERO;
    }
}
