package shop.alien.dining.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import shop.alien.dining.config.BaseRedisService;
import shop.alien.dining.service.CartService;
import shop.alien.entity.store.StoreCart;
import shop.alien.entity.store.StoreCouponUsage;
import shop.alien.entity.store.StoreCuisine;
import shop.alien.entity.store.StoreInfo;
import shop.alien.entity.store.StoreTable;
import shop.alien.entity.store.dto.AddCartItemDTO;
import shop.alien.entity.store.dto.CartDTO;
import shop.alien.entity.store.dto.CartItemDTO;
import shop.alien.mapper.StoreCartMapper;
import shop.alien.mapper.StoreCouponUsageMapper;
import shop.alien.mapper.StoreCuisineMapper;
import shop.alien.mapper.StoreInfoMapper;
import shop.alien.mapper.StoreTableMapper;
import shop.alien.dining.util.TokenUtil;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * 购物车服务实现类
 *
 * @author system
 * @since 2025-01-XX
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CartServiceImpl implements CartService {

    private static final String CART_KEY_PREFIX = "cart:table:";
    private static final String COUPON_USED_KEY_PREFIX = "coupon:used:table:";
    private static final int CART_EXPIRE_SECONDS = 24 * 60 * 60; // 24小时过期

    // 异步写入数据库的线程池（专门用于购物车数据库写入）
    private static final ExecutorService CART_DB_WRITE_EXECUTOR = Executors.newFixedThreadPool(5, r -> {
        Thread t = new Thread(r, "cart-db-write-" + System.currentTimeMillis());
        t.setDaemon(true);
        return t;
    });

    private final BaseRedisService baseRedisService;
    private final StoreTableMapper storeTableMapper;
    private final StoreCuisineMapper storeCuisineMapper;
    private final StoreCartMapper storeCartMapper;
    private final StoreCouponUsageMapper storeCouponUsageMapper;
    private final StoreInfoMapper storeInfoMapper;

    @Override
    public CartDTO getCart(Integer tableId) {
        log.info("获取购物车, tableId={}", tableId);
        String cartKey = CART_KEY_PREFIX + tableId;
        String cartJson = baseRedisService.getString(cartKey);

        CartDTO cart = new CartDTO();
        cart.setTableId(tableId);

        // 查询桌号信息
        StoreTable table = storeTableMapper.selectById(tableId);
        if (table != null) {
            cart.setTableNumber(table.getTableNumber());
            cart.setStoreId(table.getStoreId());
        }

        if (StringUtils.hasText(cartJson)) {
            try {
                JSONObject cartObj = JSON.parseObject(cartJson);
                List<CartItemDTO> items = cartObj.getList("items", CartItemDTO.class);
                if (items != null) {
                    cart.setItems(items);
                    // 计算总金额和总数量
                    BigDecimal totalAmount = items.stream()
                            .map(CartItemDTO::getSubtotalAmount)
                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                    Integer totalQuantity = items.stream()
                            .mapToInt(CartItemDTO::getQuantity)
                            .sum();
                    cart.setTotalAmount(totalAmount);
                    cart.setTotalQuantity(totalQuantity);
                } else {
                    cart.setItems(new ArrayList<>());
                    cart.setTotalAmount(BigDecimal.ZERO);
                    cart.setTotalQuantity(0);
                }
            } catch (Exception e) {
                log.error("解析购物车数据失败: {}", e.getMessage(), e);
                cart.setItems(new ArrayList<>());
                cart.setTotalAmount(BigDecimal.ZERO);
                cart.setTotalQuantity(0);
            }
        } else {
            // Redis中没有，尝试从数据库加载
            cart = loadCartFromDatabase(tableId);
        }

        return cart;
    }

    /**
     * 从数据库加载购物车
     */
    private CartDTO loadCartFromDatabase(Integer tableId) {
        log.info("从数据库加载购物车, tableId={}", tableId);
        CartDTO cart = new CartDTO();
        cart.setTableId(tableId);
        cart.setItems(new ArrayList<>());
        cart.setTotalAmount(BigDecimal.ZERO);
        cart.setTotalQuantity(0);

        // 查询桌号信息
        StoreTable table = storeTableMapper.selectById(tableId);
        if (table != null) {
            cart.setTableNumber(table.getTableNumber());
            cart.setStoreId(table.getStoreId());
        }

        // 从数据库查询购物车数据
        LambdaQueryWrapper<StoreCart> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoreCart::getTableId, tableId);
        wrapper.eq(StoreCart::getDeleteFlag, 0);
        List<StoreCart> cartList = storeCartMapper.selectList(wrapper);

        if (cartList != null && !cartList.isEmpty()) {
            List<CartItemDTO> items = cartList.stream().map(cartItem -> {
                CartItemDTO item = new CartItemDTO();
                item.setCuisineId(cartItem.getCuisineId());
                item.setCuisineName(cartItem.getCuisineName());
                item.setCuisineImage(cartItem.getCuisineImage());
                item.setUnitPrice(cartItem.getUnitPrice());
                item.setQuantity(cartItem.getQuantity());
                item.setLockedQuantity(cartItem.getLockedQuantity());
                item.setSubtotalAmount(cartItem.getSubtotalAmount());
                item.setAddUserId(cartItem.getAddUserId());
                item.setAddUserPhone(cartItem.getAddUserPhone());
                item.setRemark(cartItem.getRemark());
                return item;
            }).collect(Collectors.toList());

            cart.setItems(items);
            BigDecimal totalAmount = items.stream()
                    .map(CartItemDTO::getSubtotalAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            Integer totalQuantity = items.stream()
                    .mapToInt(CartItemDTO::getQuantity)
                    .sum();
            cart.setTotalAmount(totalAmount);
            cart.setTotalQuantity(totalQuantity);

            // 同步到Redis
            saveCartToRedis(cart);
        }

        return cart;
    }

    @Override
    public CartDTO addItem(AddCartItemDTO dto) {
        log.info("添加商品到购物车, dto={}", dto);
        // 验证桌号
        StoreTable table = storeTableMapper.selectById(dto.getTableId());
        if (table == null) {
            throw new RuntimeException("桌号不存在");
        }

        // 验证菜品
        StoreCuisine cuisine = storeCuisineMapper.selectById(dto.getCuisineId());
        if (cuisine == null) {
            throw new RuntimeException("菜品不存在");
        }
        if (cuisine.getShelfStatus() != 1) {
            throw new RuntimeException("菜品已下架");
        }

        // 获取当前用户信息
        Integer userId = TokenUtil.getCurrentUserId();
        String userPhone = TokenUtil.getCurrentUserPhone();

        // 获取购物车
        CartDTO cart = getCart(dto.getTableId());

        // 查找是否已存在该商品
        List<CartItemDTO> items = cart.getItems();
        CartItemDTO existingItem = items.stream()
                .filter(item -> item.getCuisineId().equals(dto.getCuisineId()))
                .findFirst()
                .orElse(null);

        if (existingItem != null) {
            // 商品已存在
            Integer lockedQuantity = existingItem.getLockedQuantity();
            if (lockedQuantity != null && lockedQuantity > 0) {
                // 如果商品有已下单数量，将新数量叠加到当前数量和已下单数量上
                Integer newQuantity = existingItem.getQuantity() + dto.getQuantity();
                Integer newLockedQuantity = lockedQuantity + dto.getQuantity();
                existingItem.setQuantity(newQuantity);
                existingItem.setLockedQuantity(newLockedQuantity);
                existingItem.setSubtotalAmount(existingItem.getUnitPrice()
                        .multiply(BigDecimal.valueOf(newQuantity)));
                log.info("商品已存在且有已下单数量，叠加数量, cuisineId={}, oldQuantity={}, newQuantity={}, oldOrderedQuantity={}, newOrderedQuantity={}", 
                        dto.getCuisineId(), existingItem.getQuantity() - dto.getQuantity(), newQuantity, lockedQuantity, newLockedQuantity);
            } else {
                // 商品已存在但没有已下单数量，不允许重复添加
                throw new RuntimeException("已添加过本商品");
            }
        } else {
            // 添加新商品
            CartItemDTO newItem = new CartItemDTO();
            newItem.setCuisineId(cuisine.getId());
            newItem.setCuisineName(cuisine.getName());
            newItem.setCuisineType(cuisine.getCuisineType());
            newItem.setCuisineImage(cuisine.getImages());
            newItem.setUnitPrice(cuisine.getTotalPrice());
            newItem.setQuantity(dto.getQuantity());
            newItem.setSubtotalAmount(cuisine.getTotalPrice()
                    .multiply(BigDecimal.valueOf(dto.getQuantity())));
            newItem.setAddUserId(userId);
            newItem.setAddUserPhone(userPhone);
            newItem.setRemark(dto.getRemark());
            items.add(newItem);
        }

        // 重新计算总金额和总数量
        BigDecimal totalAmount = items.stream()
                .map(CartItemDTO::getSubtotalAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        Integer totalQuantity = items.stream()
                .mapToInt(CartItemDTO::getQuantity)
                .sum();
        cart.setTotalAmount(totalAmount);
        cart.setTotalQuantity(totalQuantity);

        // 保存到Redis和数据库（双写策略）
        saveCart(cart);

        return cart;
    }

    @Override
    public CartDTO updateItemQuantity(Integer tableId, Integer cuisineId, Integer quantity) {
        log.info("更新购物车商品数量, tableId={}, cuisineId={}, quantity={}", tableId, cuisineId, quantity);
        
        // 如果数量为0或小于0，删除该商品
        if (quantity == null || quantity <= 0) {
            log.info("商品数量为0或小于0，删除商品, tableId={}, cuisineId={}", tableId, cuisineId);
            return removeItem(tableId, cuisineId);
        }

        CartDTO cart = getCart(tableId);
        List<CartItemDTO> items = cart.getItems();
        CartItemDTO item = items.stream()
                .filter(i -> i.getCuisineId().equals(cuisineId))
                .findFirst()
                .orElse(null);

        if (item != null) {
            // 商品已存在，更新数量
            // 检查已下单数量：不允许将数量减少到小于已下单数量
            Integer lockedQuantity = item.getLockedQuantity();
            if (lockedQuantity != null && lockedQuantity > 0) {
                if (quantity < lockedQuantity) {
                    throw new RuntimeException("商品数量不能少于已下单数量（" + lockedQuantity + "），该数量已下单");
                }
            }
            
            item.setQuantity(quantity);
            item.setSubtotalAmount(item.getUnitPrice()
                    .multiply(BigDecimal.valueOf(quantity)));

            // 重新计算总金额和总数量
            BigDecimal totalAmount = items.stream()
                    .map(CartItemDTO::getSubtotalAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            Integer totalQuantity = items.stream()
                    .mapToInt(CartItemDTO::getQuantity)
                    .sum();
            cart.setTotalAmount(totalAmount);
            cart.setTotalQuantity(totalQuantity);

            saveCart(cart);
        } else {
            // 商品不存在，自动添加
            log.info("商品不在购物车中，自动添加, tableId={}, cuisineId={}, quantity={}", tableId, cuisineId, quantity);
            
            // 验证菜品
            StoreCuisine cuisine = storeCuisineMapper.selectById(cuisineId);
            if (cuisine == null) {
                throw new RuntimeException("菜品不存在");
            }
            if (cuisine.getShelfStatus() != 1) {
                throw new RuntimeException("菜品已下架");
            }

            // 获取当前用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            String userPhone = TokenUtil.getCurrentUserPhone();

            // 创建新的购物车商品项
            CartItemDTO newItem = new CartItemDTO();
            newItem.setCuisineId(cuisine.getId());
            newItem.setCuisineName(cuisine.getName());
            newItem.setCuisineType(cuisine.getCuisineType());
            newItem.setCuisineImage(cuisine.getImages());
            newItem.setUnitPrice(cuisine.getTotalPrice());
            newItem.setQuantity(quantity);
            newItem.setSubtotalAmount(cuisine.getTotalPrice()
                    .multiply(BigDecimal.valueOf(quantity)));
            newItem.setAddUserId(userId);
            newItem.setAddUserPhone(userPhone);
            items.add(newItem);

            // 重新计算总金额和总数量
            BigDecimal totalAmount = items.stream()
                    .map(CartItemDTO::getSubtotalAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            Integer totalQuantity = items.stream()
                    .mapToInt(CartItemDTO::getQuantity)
                    .sum();
            cart.setTotalAmount(totalAmount);
            cart.setTotalQuantity(totalQuantity);

            // 保存到Redis和数据库（双写策略）
            saveCart(cart);
            log.info("商品已自动添加到购物车, tableId={}, cuisineId={}, quantity={}", tableId, cuisineId, quantity);
        }

        return cart;
    }

    @Override
    public CartDTO removeItem(Integer tableId, Integer cuisineId) {
        log.info("删除购物车商品, tableId={}, cuisineId={}", tableId, cuisineId);
        CartDTO cart = getCart(tableId);
        List<CartItemDTO> items = cart.getItems();
        
        // 检查是否有已下单数量，如果有则不允许删除
        CartItemDTO item = items.stream()
                .filter(i -> i.getCuisineId().equals(cuisineId))
                .findFirst()
                .orElse(null);
        
        if (item != null) {
            Integer lockedQuantity = item.getLockedQuantity();
            if (lockedQuantity != null && lockedQuantity > 0) {
                throw new RuntimeException("商品已下单，已下单数量为 " + lockedQuantity + "，不允许删除");
            }
        }
        
        items.removeIf(i -> i.getCuisineId().equals(cuisineId));

        // 重新计算总金额和总数量
        BigDecimal totalAmount = items.stream()
                .map(CartItemDTO::getSubtotalAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        Integer totalQuantity = items.stream()
                .mapToInt(CartItemDTO::getQuantity)
                .sum();
        cart.setTotalAmount(totalAmount);
        cart.setTotalQuantity(totalQuantity);

        saveCart(cart);
        return cart;
    }

    @Override
    public void clearCart(Integer tableId) {
        log.info("清空购物车（保留已下单商品）, tableId={}", tableId);
        
        // 获取购物车
        CartDTO cart = getCart(tableId);
        List<CartItemDTO> items = cart.getItems();
        
        if (items == null || items.isEmpty()) {
            log.info("购物车为空，无需清空, tableId={}", tableId);
            return;
        }
        
        // 分离已下单的商品、未下单的商品和餐具
        List<CartItemDTO> orderedItems = new ArrayList<>(); // 已下单的商品（保留，数量恢复为已下单数量）
        List<Integer> orderedCuisineIds = new ArrayList<>(); // 已下单的商品ID列表
        List<CartItemDTO> unorderedItems = new ArrayList<>(); // 未下单的商品（删除）
        CartItemDTO tablewareItem = null; // 餐具项（始终保留）
        boolean hasChanges = false; // 是否有变化（需要更新）
        
        for (CartItemDTO item : items) {
            // 餐具始终保留，不清空
            if (TABLEWARE_CUISINE_ID.equals(item.getCuisineId())) {
                tablewareItem = item;
                continue;
            }
            
            Integer lockedQuantity = item.getLockedQuantity();
            if (lockedQuantity != null && lockedQuantity > 0) {
                // 有已下单数量，保留该商品，但将当前数量恢复为已下单数量
                Integer currentQuantity = item.getQuantity();
                if (currentQuantity != null && !currentQuantity.equals(lockedQuantity)) {
                    // 当前数量不等于已下单数量，需要恢复
                    item.setQuantity(lockedQuantity);
                    item.setSubtotalAmount(item.getUnitPrice().multiply(BigDecimal.valueOf(lockedQuantity)));
                    hasChanges = true;
                    log.info("恢复已下单商品数量, cuisineId={}, oldQuantity={}, orderedQuantity={}", 
                            item.getCuisineId(), currentQuantity, lockedQuantity);
                }
                orderedItems.add(item);
                orderedCuisineIds.add(item.getCuisineId());
            } else {
                // 没有已下单数量，标记为删除
                unorderedItems.add(item);
                hasChanges = true;
            }
        }
        
        // 将餐具项添加到保留列表中，若有已下单数量则恢复为已下单数量（与菜品逻辑一致）
        if (tablewareItem != null) {
            Integer tablewareLocked = tablewareItem.getLockedQuantity();
            if (tablewareLocked != null && tablewareLocked > 0) {
                Integer currentQty = tablewareItem.getQuantity();
                if (currentQty == null || !currentQty.equals(tablewareLocked)) {
                    tablewareItem.setQuantity(tablewareLocked);
                    tablewareItem.setSubtotalAmount(tablewareItem.getUnitPrice().multiply(BigDecimal.valueOf(tablewareLocked)));
                    hasChanges = true;
                    log.info("恢复餐具数量为已下单数量, cuisineId={}, oldQuantity={}, orderedQuantity={}",
                            tablewareItem.getCuisineId(), currentQty, tablewareLocked);
                }
            }
            orderedItems.add(tablewareItem);
            orderedCuisineIds.add(tablewareItem.getCuisineId());
            log.info("保留餐具项, cuisineId={}, quantity={}", tablewareItem.getCuisineId(), tablewareItem.getQuantity());
        }
        
        // 如果有变化（有未下单的商品需要删除，或者已下单商品数量需要恢复），进行更新
        if (hasChanges) {
            // 1. 更新购物车（删除未下单商品，已下单商品数量已恢复）
            cart.setItems(orderedItems);
            // 重新计算总金额和总数量（只计算保留的商品，数量已恢复为已下单数量）
            BigDecimal totalAmount = orderedItems.stream()
                    .map(CartItemDTO::getSubtotalAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            Integer totalQuantity = orderedItems.stream()
                    .mapToInt(CartItemDTO::getQuantity)
                    .sum();
            cart.setTotalAmount(totalAmount);
            cart.setTotalQuantity(totalQuantity);
            
            // 更新Redis（保留已下单的商品，数量已恢复）
            if (orderedItems.isEmpty()) {
                // 如果所有商品都未下单，清空Redis
                String cartKey = CART_KEY_PREFIX + tableId;
                baseRedisService.delete(cartKey);
            } else {
                // 保存更新后的购物车到Redis（已下单商品数量已恢复为已下单数量）
                saveCartToRedis(cart);
            }
            
            // 2. 从数据库中逻辑删除未下单的商品（排除餐具）
            if (!unorderedItems.isEmpty()) {
                LambdaQueryWrapper<StoreCart> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(StoreCart::getTableId, tableId);
                wrapper.eq(StoreCart::getDeleteFlag, 0);
                // 排除餐具（cuisineId = -1）
                wrapper.ne(StoreCart::getCuisineId, TABLEWARE_CUISINE_ID);
                if (!orderedCuisineIds.isEmpty()) {
                    // 排除已下单的商品ID（包括餐具）
                    wrapper.notIn(StoreCart::getCuisineId, orderedCuisineIds);
                }
                List<StoreCart> cartListToDelete = storeCartMapper.selectList(wrapper);
                if (cartListToDelete != null && !cartListToDelete.isEmpty()) {
                    List<Integer> cartIds = cartListToDelete.stream()
                            .map(StoreCart::getId)
                            .collect(Collectors.toList());
                    // 使用 deleteBatchIds 进行逻辑删除（MyBatis-Plus 会自动处理 @TableLogic）
                    storeCartMapper.deleteBatchIds(cartIds);
                    log.info("删除未下单商品（已排除餐具）, tableId={}, count={}", tableId, cartIds.size());
                }
            }
            
            // 3. 更新数据库中已下单商品的数量（恢复为已下单数量）
            if (!orderedItems.isEmpty()) {
                // 保存更新后的购物车到数据库（会更新已下单商品的数量）
                saveCartToDatabase(cart);
            }
            
            // 4. 更新桌号表的购物车统计
            StoreTable table = storeTableMapper.selectById(tableId);
            if (table != null) {
                table.setCartItemCount(totalQuantity);
                table.setCartTotalAmount(totalAmount);
                storeTableMapper.updateById(table);
            }
            
            log.info("清空购物车完成（保留已下单商品和餐具，数量恢复为已下单数量）, tableId={}, 删除商品数={}, 保留商品数={}", 
                    tableId, unorderedItems.size(), orderedItems.size());
        } else {
            log.info("购物车无需更新, tableId={}", tableId);
        }
    }

    @Override
    public CartDTO migrateCart(Integer fromTableId, Integer toTableId) {
        log.info("迁移购物车, fromTableId={}, toTableId={}", fromTableId, toTableId);
        // 获取原购物车
        CartDTO fromCart = getCart(fromTableId);

        // 验证目标桌号
        StoreTable toTable = storeTableMapper.selectById(toTableId);
        if (toTable == null) {
            throw new RuntimeException("目标桌号不存在");
        }

        // 获取目标购物车
        CartDTO toCart = getCart(toTableId);

        // 合并购物车(如果目标桌号已有商品,则合并)
        List<CartItemDTO> mergedItems = new ArrayList<>(toCart.getItems());
        for (CartItemDTO fromItem : fromCart.getItems()) {
            CartItemDTO existingItem = mergedItems.stream()
                    .filter(item -> item.getCuisineId().equals(fromItem.getCuisineId()))
                    .findFirst()
                    .orElse(null);

            if (existingItem != null) {
                // 合并数量
                int newQuantity = (existingItem.getQuantity() != null ? existingItem.getQuantity() : 0)
                        + (fromItem.getQuantity() != null ? fromItem.getQuantity() : 0);
                existingItem.setQuantity(newQuantity);
                existingItem.setSubtotalAmount(existingItem.getUnitPrice()
                        .multiply(BigDecimal.valueOf(newQuantity)));
                // 合并已下单数量（换桌后目标桌需保留两边的已下单数量）
                int toLocked = existingItem.getLockedQuantity() != null ? existingItem.getLockedQuantity() : 0;
                int fromLocked = fromItem.getLockedQuantity() != null ? fromItem.getLockedQuantity() : 0;
                existingItem.setLockedQuantity(toLocked + fromLocked > 0 ? toLocked + fromLocked : null);
            } else {
                mergedItems.add(fromItem);
            }
        }

        toCart.setItems(mergedItems);
        toCart.setTableId(toTableId);
        toCart.setTableNumber(toTable.getTableNumber());
        toCart.setStoreId(toTable.getStoreId());

        // 重新计算总金额和总数量
        BigDecimal totalAmount = mergedItems.stream()
                .map(CartItemDTO::getSubtotalAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        Integer totalQuantity = mergedItems.stream()
                .mapToInt(CartItemDTO::getQuantity)
                .sum();
        toCart.setTotalAmount(totalAmount);
        toCart.setTotalQuantity(totalQuantity);

        // 保存目标购物车
        saveCart(toCart);

        // 清空原购物车
        clearCart(fromTableId);

        // 迁移优惠券使用标记
        if (hasUsedCoupon(fromTableId)) {
            String couponUsedKey = COUPON_USED_KEY_PREFIX + fromTableId;
            String couponId = baseRedisService.getString(couponUsedKey);
            if (StringUtils.hasText(couponId)) {
                markCouponUsed(toTableId, Integer.parseInt(couponId));
                clearCouponUsed(fromTableId);
            }
        }

        return toCart;
    }

    @Override
    public boolean hasUsedCoupon(Integer tableId) {
        // 先查Redis
        String couponUsedKey = COUPON_USED_KEY_PREFIX + tableId;
        String couponId = baseRedisService.getString(couponUsedKey);
        if (StringUtils.hasText(couponId)) {
            return true;
        }

        // Redis中没有，查数据库
        LambdaQueryWrapper<StoreCouponUsage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoreCouponUsage::getTableId, tableId);
        wrapper.eq(StoreCouponUsage::getDeleteFlag, 0);
        wrapper.in(StoreCouponUsage::getUsageStatus, 0, 1, 2); // 已标记使用、已下单、已支付
        wrapper.orderByDesc(StoreCouponUsage::getCreatedTime);
        wrapper.last("LIMIT 1");
        StoreCouponUsage usage = storeCouponUsageMapper.selectOne(wrapper);
        return usage != null;
    }

    @Override
    public void markCouponUsed(Integer tableId, Integer couponId) {
        // 保存到Redis
        String couponUsedKey = COUPON_USED_KEY_PREFIX + tableId;
        baseRedisService.setString(couponUsedKey, String.valueOf(couponId), (long) CART_EXPIRE_SECONDS);

        // 保存到数据库
        StoreTable table = storeTableMapper.selectById(tableId);
        if (table == null) {
            log.warn("桌号不存在, tableId={}", tableId);
            return;
        }

        // 检查是否已存在
        LambdaQueryWrapper<StoreCouponUsage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoreCouponUsage::getTableId, tableId);
        wrapper.eq(StoreCouponUsage::getCouponId, couponId);
        wrapper.eq(StoreCouponUsage::getDeleteFlag, 0);
        StoreCouponUsage existing = storeCouponUsageMapper.selectOne(wrapper);

        if (existing == null) {
            Date now = new Date();
            StoreCouponUsage usage = new StoreCouponUsage();
            usage.setTableId(tableId);
            usage.setStoreId(table.getStoreId());
            usage.setCouponId(couponId);
            usage.setUsageStatus(0); // 已标记使用
            usage.setCreatedTime(now);
            usage.setUpdatedTime(now); // 设置更新时间，避免数据库约束错误
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId != null) {
                usage.setCreatedUserId(userId);
            }
            storeCouponUsageMapper.insert(usage);
        }

        // 更新桌号表的优惠券ID
        table.setCurrentCouponId(couponId);
        storeTableMapper.updateById(table);
    }

    @Override
    public void clearCouponUsed(Integer tableId) {
        // 清空Redis
        String couponUsedKey = COUPON_USED_KEY_PREFIX + tableId;
        baseRedisService.delete(couponUsedKey);

        // 更新数据库（逻辑删除未下单的记录，使用 MyBatis-Plus 的 deleteBatchIds）
        LambdaQueryWrapper<StoreCouponUsage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoreCouponUsage::getTableId, tableId);
        wrapper.eq(StoreCouponUsage::getDeleteFlag, 0);
        wrapper.eq(StoreCouponUsage::getUsageStatus, 0); // 只删除已标记使用但未下单的
        List<StoreCouponUsage> usageList = storeCouponUsageMapper.selectList(wrapper);
        if (usageList != null && !usageList.isEmpty()) {
            List<Integer> usageIds = usageList.stream()
                    .map(StoreCouponUsage::getId)
                    .collect(Collectors.toList());
            // 使用 deleteBatchIds 进行逻辑删除（MyBatis-Plus 会自动处理 @TableLogic）
            storeCouponUsageMapper.deleteBatchIds(usageIds);
        }

        // 更新桌号表的优惠券ID
        StoreTable table = storeTableMapper.selectById(tableId);
        if (table != null) {
            table.setCurrentCouponId(null);
            storeTableMapper.updateById(table);
        }
    }

    /**
     * 餐具的特殊ID（用于标识餐具项）
     */
    private static final Integer TABLEWARE_CUISINE_ID = -1;
    private static final String TABLEWARE_NAME = "餐具费";

    /**
     * 获取餐具单价（从 store_info 表获取）
     *
     * @param storeId 门店ID
     * @return 餐具单价（BigDecimal），如果门店不存在或未设置餐具费，返回 0.00
     */
    private BigDecimal getTablewareUnitPrice(Integer storeId) {
        if (storeId == null) {
            log.warn("门店ID为空，返回默认餐具单价 0.00");
            return BigDecimal.ZERO;
        }
        StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
        if (storeInfo == null) {
            log.warn("门店不存在, storeId={}，返回默认餐具单价 0.00", storeId);
            return BigDecimal.ZERO;
        }
        Integer tablewareFee = storeInfo.getTablewareFee();
        if (tablewareFee == null || tablewareFee < 0) {
            log.warn("门店餐具费未设置或无效, storeId={}, tablewareFee={}，返回默认餐具单价 0.00", storeId, tablewareFee);
            return BigDecimal.ZERO;
        }
        return BigDecimal.valueOf(tablewareFee);
    }

    @Override
    public CartDTO setDinerCount(Integer tableId, Integer dinerCount) {
        log.info("设置用餐人数, tableId={}, dinerCount={}", tableId, dinerCount);
        
        if (dinerCount == null || dinerCount <= 0) {
            throw new RuntimeException("用餐人数必须大于0");
        }

        // 获取购物车
        CartDTO cart = getCart(tableId);
        List<CartItemDTO> items = cart.getItems();

        // 获取门店ID和餐具单价
        Integer storeId = cart.getStoreId();
        if (storeId == null) {
            // 如果购物车中没有门店ID，从桌号获取
            StoreTable table = storeTableMapper.selectById(tableId);
            if (table != null) {
                storeId = table.getStoreId();
            }
        }
        BigDecimal tablewareUnitPrice = getTablewareUnitPrice(storeId);

        // 商铺未设置餐具费时，不往购物车加餐具；若已有餐具项则移除
        if (tablewareUnitPrice == null || tablewareUnitPrice.compareTo(BigDecimal.ZERO) <= 0) {
            log.info("门店未设置餐具费, storeId={}，设置就餐人数时不添加餐具", storeId);
            CartItemDTO existing = items.stream()
                    .filter(item -> TABLEWARE_CUISINE_ID.equals(item.getCuisineId()))
                    .findFirst()
                    .orElse(null);
            if (existing != null) {
                items.remove(existing);
            }
        } else {
            // 查找是否已存在餐具项
            CartItemDTO tablewareItem = items.stream()
                    .filter(item -> TABLEWARE_CUISINE_ID.equals(item.getCuisineId()))
                    .findFirst()
                    .orElse(null);

            Integer userId = TokenUtil.getCurrentUserId();
            String userPhone = TokenUtil.getCurrentUserPhone();

            if (tablewareItem != null) {
                Integer lockedQuantity = tablewareItem.getLockedQuantity();
                if (lockedQuantity != null && lockedQuantity > 0 && dinerCount < lockedQuantity) {
                    throw new RuntimeException("餐具数量不能少于已下单数量（" + lockedQuantity + "）");
                }
                tablewareItem.setQuantity(dinerCount);
                tablewareItem.setUnitPrice(tablewareUnitPrice);
                tablewareItem.setSubtotalAmount(tablewareUnitPrice.multiply(BigDecimal.valueOf(dinerCount)));
            } else {
                CartItemDTO newTablewareItem = new CartItemDTO();
                newTablewareItem.setCuisineId(TABLEWARE_CUISINE_ID);
                newTablewareItem.setCuisineName(TABLEWARE_NAME);
                newTablewareItem.setCuisineType(0);
                newTablewareItem.setCuisineImage("");
                newTablewareItem.setUnitPrice(tablewareUnitPrice);
                newTablewareItem.setQuantity(dinerCount);
                newTablewareItem.setSubtotalAmount(tablewareUnitPrice.multiply(BigDecimal.valueOf(dinerCount)));
                newTablewareItem.setAddUserId(userId);
                newTablewareItem.setAddUserPhone(userPhone);
                items.add(newTablewareItem);
            }
        }

        // 重新计算总金额和总数量
        BigDecimal totalAmount = items.stream()
                .map(CartItemDTO::getSubtotalAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        Integer totalQuantity = items.stream()
                .mapToInt(CartItemDTO::getQuantity)
                .sum();
        cart.setTotalAmount(totalAmount);
        cart.setTotalQuantity(totalQuantity);

        // 保存到Redis和数据库（双写策略）
        saveCart(cart);

        return cart;
    }

    @Override
    public CartDTO updateTablewareQuantity(Integer tableId, Integer quantity) {
        log.info("更新餐具数量, tableId={}, quantity={}", tableId, quantity);
        
        if (quantity == null || quantity < 0) {
            throw new RuntimeException("餐具数量不能小于0");
        }

        if (quantity == 0) {
            // 数量为0时，删除餐具项
            return removeItem(tableId, TABLEWARE_CUISINE_ID);
        }

        // 获取购物车
        CartDTO cart = getCart(tableId);
        List<CartItemDTO> items = cart.getItems();

        // 获取门店ID和餐具单价
        Integer storeId = cart.getStoreId();
        if (storeId == null) {
            StoreTable table = storeTableMapper.selectById(tableId);
            if (table != null) {
                storeId = table.getStoreId();
            }
        }
        BigDecimal tablewareUnitPrice = getTablewareUnitPrice(storeId);

        // 商铺未设置餐具费（单价为0或未配置）时，不往购物车加餐具；若已有餐具项则移除
        if (tablewareUnitPrice == null || tablewareUnitPrice.compareTo(BigDecimal.ZERO) <= 0) {
            log.info("门店未设置餐具费, storeId={}，不添加餐具到购物车", storeId);
            CartItemDTO existing = items.stream()
                    .filter(item -> TABLEWARE_CUISINE_ID.equals(item.getCuisineId()))
                    .findFirst()
                    .orElse(null);
            if (existing != null) {
                items.remove(existing);
                BigDecimal totalAmount = items.stream()
                        .map(CartItemDTO::getSubtotalAmount)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                Integer totalQuantity = items.stream()
                        .mapToInt(CartItemDTO::getQuantity)
                        .sum();
                cart.setTotalAmount(totalAmount);
                cart.setTotalQuantity(totalQuantity);
                saveCart(cart);
            }
            return cart;
        }

        // 查找餐具项
        CartItemDTO tablewareItem = items.stream()
                .filter(item -> TABLEWARE_CUISINE_ID.equals(item.getCuisineId()))
                .findFirst()
                .orElse(null);

        if (tablewareItem == null) {
            // 如果不存在餐具项，创建一个
            Integer userId = TokenUtil.getCurrentUserId();
            String userPhone = TokenUtil.getCurrentUserPhone();
            
            tablewareItem = new CartItemDTO();
            tablewareItem.setCuisineId(TABLEWARE_CUISINE_ID);
            tablewareItem.setCuisineName(TABLEWARE_NAME);
            tablewareItem.setCuisineType(0); // 0表示餐具
            tablewareItem.setCuisineImage("");
            tablewareItem.setUnitPrice(tablewareUnitPrice);
            tablewareItem.setAddUserId(userId);
            tablewareItem.setAddUserPhone(userPhone);
            items.add(tablewareItem);
        } else {
            // 下单后只能增不能减：已有已下单数量时，数量不能少于已下单数量
            Integer lockedQuantity = tablewareItem.getLockedQuantity();
            if (lockedQuantity != null && lockedQuantity > 0 && quantity < lockedQuantity) {
                throw new RuntimeException("餐具数量不能少于已下单数量（" + lockedQuantity + "）");
            }
            // 如果已存在，更新单价（可能门店修改了餐具费）
            tablewareItem.setUnitPrice(tablewareUnitPrice);
        }

        // 更新数量
        tablewareItem.setQuantity(quantity);
        tablewareItem.setSubtotalAmount(tablewareUnitPrice.multiply(BigDecimal.valueOf(quantity)));

        // 重新计算总金额和总数量
        BigDecimal totalAmount = items.stream()
                .map(CartItemDTO::getSubtotalAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        Integer totalQuantity = items.stream()
                .mapToInt(CartItemDTO::getQuantity)
                .sum();
        cart.setTotalAmount(totalAmount);
        cart.setTotalQuantity(totalQuantity);

        // 保存到Redis和数据库（双写策略）
        saveCart(cart);

        return cart;
    }

    @Override
    public CartDTO lockCartItems(Integer tableId) {
        log.info("锁定购物车商品数量（设置已下单数量）, tableId={}", tableId);
        
        // 获取购物车
        CartDTO cart = getCart(tableId);
        List<CartItemDTO> items = cart.getItems();
        
        if (items == null || items.isEmpty()) {
            log.warn("购物车为空，无需锁定, tableId={}", tableId);
            return cart;
        }
        
        // 遍历所有商品，将当前数量设置为已下单数量
        boolean hasChanges = false;
        for (CartItemDTO item : items) {
            Integer currentQuantity = item.getQuantity();
            Integer lockedQuantity = item.getLockedQuantity();
            
            if (currentQuantity != null && currentQuantity > 0) {
                if (lockedQuantity == null || lockedQuantity == 0) {
                    // 如果还没有已下单数量，将当前数量设置为已下单数量
                    item.setLockedQuantity(currentQuantity);
                    hasChanges = true;
                    log.info("设置商品已下单数量, cuisineId={}, orderedQuantity={}", item.getCuisineId(), currentQuantity);
                } else if (currentQuantity > lockedQuantity) {
                    // 如果已有已下单数量，且当前数量大于已下单数量（再次下单的情况），将新增数量累加到已下单数量
                    Integer newLockedQuantity = lockedQuantity + (currentQuantity - lockedQuantity);
                    item.setLockedQuantity(newLockedQuantity);
                    hasChanges = true;
                    log.info("更新商品已下单数量, cuisineId={}, oldOrderedQuantity={}, newOrderedQuantity={}", 
                            item.getCuisineId(), lockedQuantity, newLockedQuantity);
                }
            }
        }
        
        // 如果有变化，保存购物车
        if (hasChanges) {
            saveCart(cart);
        }
        
        return cart;
    }

    @Override
    public CartDTO unlockCartItems(Integer tableId) {
        log.info("解锁购物车商品数量（清除已下单数量）, tableId={}", tableId);
        
        // 获取购物车
        CartDTO cart = getCart(tableId);
        List<CartItemDTO> items = cart.getItems();
        
        if (items == null || items.isEmpty()) {
            log.info("购物车为空，无需解锁, tableId={}", tableId);
            return cart;
        }
        
        // 遍历所有商品，清除已下单数量（lockedQuantity）
        boolean hasChanges = false;
        for (CartItemDTO item : items) {
            if (item.getLockedQuantity() != null && item.getLockedQuantity() > 0) {
                // 清除已下单数量，允许重新下单
                item.setLockedQuantity(null);
                hasChanges = true;
                log.info("清除商品已下单数量, cuisineId={}", item.getCuisineId());
            }
        }
        
        // 如果有变化，保存购物车
        if (hasChanges) {
            saveCart(cart);
            log.info("解锁购物车商品数量完成, tableId={}", tableId);
        } else {
            log.info("购物车无需解锁, tableId={}", tableId);
        }
        
        return cart;
    }

    /**
     * 保存购物车到Redis和数据库（优化后的双写策略）
     * Redis同步写入（保证实时性），数据库异步批量写入（提高性能）
     */
    private void saveCart(CartDTO cart) {
        // 1. 同步保存到Redis（保证实时性）
        saveCartToRedis(cart);

        // 2. 异步保存到数据库（不阻塞主流程，提高性能）
        CompletableFuture.runAsync(() -> {
            try {
                saveCartToDatabase(cart);
            } catch (Exception e) {
                log.error("异步保存购物车到数据库失败, tableId={}, error={}", cart.getTableId(), e.getMessage(), e);
            }
        }, CART_DB_WRITE_EXECUTOR);
    }

    /**
     * 保存购物车到Redis
     */
    private void saveCartToRedis(CartDTO cart) {
        String cartKey = CART_KEY_PREFIX + cart.getTableId();
        String cartJson = JSON.toJSONString(cart);
        baseRedisService.setString(cartKey, cartJson, (long) CART_EXPIRE_SECONDS);
    }

    /**
     * 保存购物车到数据库（优化后的批量操作版本）
     * 使用批量逻辑删除和批量插入，提高性能
     */
    private void saveCartToDatabase(CartDTO cart) {
        try {
            Date now = new Date();
            Integer userId = TokenUtil.getCurrentUserId();

            // 1. 批量逻辑删除该桌号的所有购物车记录（使用 MyBatis-Plus 的 deleteBatchIds）
            LambdaQueryWrapper<StoreCart> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(StoreCart::getTableId, cart.getTableId())
                    .eq(StoreCart::getDeleteFlag, 0);
            List<StoreCart> existingCartList = storeCartMapper.selectList(queryWrapper);
            if (existingCartList != null && !existingCartList.isEmpty()) {
                List<Integer> cartIds = existingCartList.stream()
                        .map(StoreCart::getId)
                        .collect(Collectors.toList());
                // 使用 deleteBatchIds 进行逻辑删除（MyBatis-Plus 会自动处理 @TableLogic）
                storeCartMapper.deleteBatchIds(cartIds);
            }

            // 2. 批量插入新的购物车记录
            if (cart.getItems() != null && !cart.getItems().isEmpty()) {
                List<StoreCart> cartList = new ArrayList<>(cart.getItems().size());
                for (CartItemDTO item : cart.getItems()) {
                    StoreCart storeCart = new StoreCart();
                    storeCart.setTableId(cart.getTableId());
                    storeCart.setStoreId(cart.getStoreId());
                    storeCart.setCuisineId(item.getCuisineId());
                    storeCart.setCuisineName(item.getCuisineName());
                    storeCart.setCuisineImage(item.getCuisineImage());
                    storeCart.setUnitPrice(item.getUnitPrice());
                    storeCart.setQuantity(item.getQuantity());
                    storeCart.setLockedQuantity(item.getLockedQuantity());
                    storeCart.setSubtotalAmount(item.getSubtotalAmount());
                    storeCart.setAddUserId(item.getAddUserId());
                    storeCart.setAddUserPhone(item.getAddUserPhone());
                    storeCart.setRemark(item.getRemark());
                    storeCart.setDeleteFlag(0);
                    storeCart.setCreatedTime(now);
                    storeCart.setCreatedUserId(userId);
                    storeCart.setUpdatedTime(now);
                    cartList.add(storeCart);
                }

                // 批量插入（如果数量较少，直接循环插入；如果数量较多，可以考虑分批插入）
                if (cartList.size() <= 50) {
                    // 小批量直接插入
                    for (StoreCart storeCart : cartList) {
                        storeCartMapper.insert(storeCart);
                    }
                } else {
                    // 大批量分批插入（每批50条）
                    int batchSize = 50;
                    for (int i = 0; i < cartList.size(); i += batchSize) {
                        int end = Math.min(i + batchSize, cartList.size());
                        List<StoreCart> batch = cartList.subList(i, end);
                        for (StoreCart storeCart : batch) {
                            storeCartMapper.insert(storeCart);
                        }
                    }
                }
            }

            // 3. 更新桌号表的购物车统计
            StoreTable table = storeTableMapper.selectById(cart.getTableId());
            if (table != null) {
                table.setCartItemCount(cart.getTotalQuantity());
                table.setCartTotalAmount(cart.getTotalAmount());
                storeTableMapper.updateById(table);
            }

            log.debug("购物车数据已异步保存到数据库, tableId={}, itemCount={}", 
                    cart.getTableId(), cart.getItems() != null ? cart.getItems().size() : 0);
        } catch (Exception e) {
            log.error("保存购物车到数据库失败, tableId={}, error={}", cart.getTableId(), e.getMessage(), e);
            // 数据库保存失败不影响Redis，继续执行
        }
    }
}
