package shop.alien.dining.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import shop.alien.dining.service.CartService;
import shop.alien.dining.service.SseService;
import shop.alien.dining.service.StoreOrderService;
import shop.alien.dining.util.TokenUtil;
import shop.alien.entity.result.R;
import shop.alien.entity.store.*;
import shop.alien.entity.store.dto.AddCartItemDTO;
import shop.alien.entity.store.dto.CartDTO;
import shop.alien.entity.store.dto.ChangeTableDTO;
import shop.alien.entity.store.dto.CreateOrderDTO;
import shop.alien.entity.store.vo.OrderChangeLogBatchVO;
import shop.alien.entity.store.vo.OrderInfoVO;
import shop.alien.entity.store.vo.OrderDetailWithChangeLogVO;
import shop.alien.entity.store.vo.StoreOrderPageVO;
import shop.alien.mapper.StoreInfoMapper;
import shop.alien.mapper.StoreOrderDetailMapper;
import shop.alien.mapper.StoreTableMapper;

import javax.validation.Valid;
import java.util.List;

/**
 * 订单管理控制器
 *
 * @author system
 * @since 2025-01-XX
 */
@Slf4j
@Api(tags = {"小程序-订单管理"})
@CrossOrigin
@RestController
@RequestMapping("/store/order")
@RequiredArgsConstructor
public class StoreOrderController {

    private final StoreOrderService orderService;
    private final CartService cartService;
    private final SseService sseService;
    private final StoreOrderDetailMapper orderDetailMapper;
    private final StoreTableMapper storeTableMapper;
    private final StoreInfoMapper storeInfoMapper;

    @ApiOperation(value = "获取购物车", notes = "根据桌号ID获取购物车信息")
    @GetMapping("/cart/{tableId}")
    public R<CartDTO> getCart(@ApiParam(value = "桌号ID", required = true) @PathVariable Integer tableId) {
        log.info("StoreOrderController.getCart?tableId={}", tableId);
        try {
            // 验证 token
            if (!TokenUtil.hasValidToken()) {
                return R.fail("用户未登录");
            }
            CartDTO cart = cartService.getCart(tableId);
            return R.data(cart);
        } catch (Exception e) {
            log.error("获取购物车失败: {}", e.getMessage(), e);
            return R.fail("获取购物车失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "添加商品到购物车", notes = "添加商品到购物车，并推送SSE和WebSocket消息")
    @PostMapping("/cart/add")
    public R<CartDTO> addCartItem(@Valid @RequestBody AddCartItemDTO dto) {
        log.info("StoreOrderController.addCartItem?dto={}", dto);
        try {
            // 验证 token（用户信息在 CartService 中从 token 获取）
            if (!TokenUtil.hasValidToken()) {
                return R.fail("用户未登录");
            }
            CartDTO cart = cartService.addItem(dto);
            // 推送购物车更新消息（SSE）
            sseService.pushCartUpdate(dto.getTableId(), cart);
            // 推送购物车更新消息（WebSocket）
//            CartWebSocketProcess.pushCartUpdate(dto.getTableId(), cart);
            return R.data(cart);
        } catch (Exception e) {
            log.error("添加商品到购物车失败: {}", e.getMessage(), e);
            return R.fail("添加商品到购物车失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "更新购物车商品数量", notes = "更新购物车中商品的数量，并推送SSE和WebSocket消息")
    @PutMapping("/cart/update")
    public R<CartDTO> updateCartItem(
            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
            @ApiParam(value = "菜品ID", required = true) @RequestParam Integer cuisineId,
            @ApiParam(value = "数量", required = true) @RequestParam Integer quantity) {
        log.info("StoreOrderController.updateCartItem?tableId={}, cuisineId={}, quantity={}", tableId, cuisineId, quantity);
        try {
            // 验证 token
            if (!TokenUtil.hasValidToken()) {
                return R.fail("用户未登录");
            }
            CartDTO cart = cartService.updateItemQuantity(tableId, cuisineId, quantity);
            // 推送购物车更新消息（SSE）
            sseService.pushCartUpdate(tableId, cart);
            // 推送购物车更新消息（WebSocket）
//            CartWebSocketProcess.pushCartUpdate(tableId, cart);
            return R.data(cart);
        } catch (Exception e) {
            log.error("更新购物车商品数量失败: {}", e.getMessage(), e);
            return R.fail("更新购物车商品数量失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "删除购物车商品", notes = "从购物车中删除商品，并推送SSE和WebSocket消息")
    @DeleteMapping("/cart/remove")
    public R<CartDTO> removeCartItem(
            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
            @ApiParam(value = "菜品ID", required = true) @RequestParam Integer cuisineId) {
        log.info("StoreOrderController.removeCartItem?tableId={}, cuisineId={}", tableId, cuisineId);
        try {
            // 验证 token
            if (!TokenUtil.hasValidToken()) {
                return R.fail("用户未登录");
            }
            CartDTO cart = cartService.removeItem(tableId, cuisineId);
            // 推送购物车更新消息（SSE）
            sseService.pushCartUpdate(tableId, cart);
            // 推送购物车更新消息（WebSocket）
//            CartWebSocketProcess.pushCartUpdate(tableId, cart);
            return R.data(cart);
        } catch (Exception e) {
            log.error("删除购物车商品失败: {}", e.getMessage(), e);
            return R.fail("删除购物车商品失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "清空购物车", notes = "清空购物车中所有商品（保留餐具和已下单商品），并推送SSE和WebSocket消息")
    @DeleteMapping("/cart/clear")
    public R<CartDTO> clearCart(
            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
        log.info("StoreOrderController.clearCart?tableId={}", tableId);
        try {
            // 验证 token
            if (!TokenUtil.hasValidToken()) {
                return R.fail("用户未登录");
            }
            
            // 清空购物车（会自动保留已下单的商品和餐具）
            cartService.clearCart(tableId);
            
            // 获取清空后的购物车（包含保留的餐具和已下单商品）
            CartDTO cart = cartService.getCart(tableId);
            
            // 推送购物车更新消息（SSE）
            sseService.pushCartUpdate(tableId, cart);
            // 推送购物车更新消息（WebSocket）
//            CartWebSocketProcess.pushCartUpdate(tableId, cart);
            
            return R.data(cart);
        } catch (Exception e) {
            log.error("清空购物车失败: {}", e.getMessage(), e);
            return R.fail("清空购物车失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "设置用餐人数", notes = "设置用餐人数，自动添加或更新餐具到购物车")
    @PostMapping("/cart/set-diner-count")
    public R<CartDTO> setDinerCount(
            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
            @ApiParam(value = "用餐人数", required = true) @RequestParam Integer dinerCount) {
        log.info("StoreOrderController.setDinerCount?tableId={}, dinerCount={}", tableId, dinerCount);
        try {
            // 验证 token
            if (!TokenUtil.hasValidToken()) {
                return R.fail("用户未登录");
            }
            if (dinerCount == null || dinerCount <= 0) {
                return R.fail("用餐人数必须大于0");
            }
            CartDTO cart = cartService.setDinerCount(tableId, dinerCount);
            // 推送购物车更新消息（SSE）
            sseService.pushCartUpdate(tableId, cart);
            // 推送购物车更新消息（WebSocket）
//            CartWebSocketProcess.pushCartUpdate(tableId, cart);
            return R.data(cart);
        } catch (Exception e) {
            log.error("设置用餐人数失败: {}", e.getMessage(), e);
            return R.fail("设置用餐人数失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "更新餐具数量", notes = "更新购物车中餐具的数量，并推送SSE和WebSocket消息。餐具数量为0或未传时不往购物车加餐具（0会移除已有餐具项）")
    @PutMapping("/cart/update-tableware")
    public R<CartDTO> updateTablewareQuantity(
            @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
            @ApiParam(value = "餐具数量，0或未传则不往购物车加餐具") @RequestParam(required = false) Integer quantity) {
        log.info("StoreOrderController.updateTablewareQuantity?tableId={}, quantity={}", tableId, quantity);
        try {
            // 验证 token
            if (!TokenUtil.hasValidToken()) {
                return R.fail("用户未登录");
            }
            if (quantity != null && quantity < 0) {
                return R.fail("餐具数量不能小于0");
            }
            // 餐具数量为 0 或 null 时不往购物车加餐具：0 则移除已有餐具项，null 则直接返回当前购物车
            if (quantity == null) {
                CartDTO cart = cartService.getCart(tableId);
                sseService.pushCartUpdate(tableId, cart);
                return R.data(cart);
            }
            if (quantity == 0) {
                CartDTO cart = cartService.updateTablewareQuantity(tableId, 0);
                sseService.pushCartUpdate(tableId, cart);
                return R.data(cart);
            }
            CartDTO cart = cartService.updateTablewareQuantity(tableId, quantity);
            // 推送购物车更新消息（SSE）
            sseService.pushCartUpdate(tableId, cart);
            // 推送购物车更新消息（WebSocket）
//            CartWebSocketProcess.pushCartUpdate(tableId, cart);
            return R.data(cart);
        } catch (Exception e) {
            log.error("更新餐具数量失败: {}", e.getMessage(), e);
            return R.fail("更新餐具数量失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "创建订单(下单)", notes = "从购物车创建订单，不立即支付。备注：创建/更新时传入，更新订单(加餐)时为覆盖")
    @PostMapping("/create")
    public R<shop.alien.entity.store.vo.OrderSuccessVO> createOrder(@Valid @RequestBody CreateOrderDTO dto) {
        log.info("StoreOrderController.createOrder?dto={}", dto);
        try {
            // 验证 token（用户信息在 StoreOrderService 中从 token 获取）
            if (!TokenUtil.hasValidToken()) {
                return R.fail("用户未登录");
            }
            // 限制备注长度
            if (dto.getRemark() != null && dto.getRemark().length() > 30) {
                dto.setRemark(dto.getRemark().substring(0, 30));
            }

            // 设置不立即支付
            dto.setImmediatePay(0);
            StoreOrder order = orderService.createOrder(dto);

            // 转换为OrderSuccessVO
            shop.alien.entity.store.vo.OrderSuccessVO vo = new shop.alien.entity.store.vo.OrderSuccessVO();
            vo.setOrderId(order.getId());
            vo.setOrderNo(order.getOrderNo());
            vo.setTableNumber(order.getTableNumber());
            vo.setDinerCount(order.getDinerCount());
            vo.setOrderStatus(order.getOrderStatus());

            // 查询门店信息
            StoreInfo storeInfo = storeInfoMapper.selectById(order.getStoreId());
            vo.setStoreName(storeInfo != null ? storeInfo.getStoreName() : null);

            // 推送订单创建消息
            sseService.pushCartUpdate(dto.getTableId(), order);
            return R.data(vo);
        } catch (Exception e) {
            log.error("创建订单失败: {}", e.getMessage(), e);
            return R.fail("创建订单失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "支付订单", notes = "支付订单，支付成功后订单状态变为已支付(1)，需要单独调用完成订单接口将订单状态改为已完成(3)")
    @PostMapping("/pay/{orderId}")
    public R<Object> payOrder(
            @ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId,
            @ApiParam(value = "支付方式(1:微信, 2:支付宝, 3:现金)", required = true) @RequestParam Integer payType) {
        log.info("StoreOrderController.payOrder?orderId={}, payType={}", orderId, payType);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            
            StoreOrder order = orderService.getOrderById(orderId);
            if (order == null) {
                return R.fail("订单不存在");
            }

            if (order.getOrderStatus() != 0) {
                return R.fail("订单状态不正确，无法支付");
            }

            // 如果是微信支付，调用微信支付接口
            if (payType == 1) {
                // TODO: 调用微信支付接口，返回支付参数
                // 这里需要集成微信支付SDK，返回支付参数给前端拉起支付
                // 支付成功后通过回调接口更新订单状态
                // 暂时先更新订单状态为已支付（实际应该等支付回调）
                order = orderService.payOrder(orderId, payType);
                return R.data(order);
            } else {
                // 其他支付方式（支付宝、现金）直接更新为已支付
                order = orderService.payOrder(orderId, payType);
                return R.data(order);
            }
        } catch (Exception e) {
            log.error("支付订单失败: {}", e.getMessage(), e);
            return R.fail("支付订单失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "取消订单", notes = "取消订单")
    @PostMapping("/cancel/{orderId}")
    public R<Boolean> cancelOrder(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
        log.info("StoreOrderController.cancelOrder?orderId={}", orderId);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            boolean result = orderService.cancelOrder(orderId);
            return R.data(result);
        } catch (Exception e) {
            log.error("取消订单失败: {}", e.getMessage(), e);
            return R.fail("取消订单失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "查询订单详情", notes = "根据订单ID查询订单详情，包含订单基本信息和按批次分组的变更记录，用于展示每次下单/加餐都加了什么商品")
    @GetMapping("/detail/{orderId}")
    public R<OrderDetailWithChangeLogVO> getOrderDetail(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
        log.info("StoreOrderController.getOrderDetail?orderId={}", orderId);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            OrderDetailWithChangeLogVO orderDetail = orderService.getOrderDetailWithChangeLog(orderId);
            return R.data(orderDetail);
        } catch (Exception e) {
            log.error("查询订单详情失败: {}", e.getMessage(), e);
            return R.fail("查询订单详情失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "查询订单明细", notes = "根据订单ID查询订单明细列表")
    @GetMapping("/detail/list/{orderId}")
    public R<List<StoreOrderDetail>> getOrderDetailList(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
        log.info("StoreOrderController.getOrderDetailList?orderId={}", orderId);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<StoreOrderDetail> wrapper =
                    new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>();
            wrapper.eq(StoreOrderDetail::getOrderId, orderId);
            wrapper.eq(StoreOrderDetail::getDeleteFlag, 0);
            wrapper.orderByDesc(StoreOrderDetail::getCreatedTime);
            List<StoreOrderDetail> details = orderDetailMapper.selectList(wrapper);
            return R.data(details);
        } catch (Exception e) {
            log.error("查询订单明细失败: {}", e.getMessage(), e);
            return R.fail("查询订单明细失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "查询订单信息", notes = "根据订单ID查询订单完整信息（包含订单基本信息、菜品清单、价格明细）")
    @GetMapping("/info/{orderId}")
    public R<OrderInfoVO> getOrderInfo(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
        log.info("StoreOrderController.getOrderInfo?orderId={}", orderId);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            OrderInfoVO orderInfo = orderService.getOrderInfo(orderId);
            return R.data(orderInfo);
        } catch (Exception e) {
            log.error("查询订单信息失败: {}", e.getMessage(), e);
            return R.fail("查询订单信息失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "查询订单变更记录", notes = "根据订单ID查询订单的所有变更记录（按批次分组），用于展示每次下单/加餐都加了什么商品")
    @GetMapping("/change-log/{orderId}")
    public R<List<OrderChangeLogBatchVO>> getOrderChangeLogs(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
        log.info("StoreOrderController.getOrderChangeLogs?orderId={}", orderId);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            List<OrderChangeLogBatchVO> changeLogs = orderService.getOrderChangeLogs(orderId);
            return R.data(changeLogs);
        } catch (Exception e) {
            log.error("查询订单变更记录失败: {}", e.getMessage(), e);
            return R.fail("查询订单变更记录失败: " + e.getMessage());
        }
    }


    @ApiOperation(value = "分页查询订单列表", notes = "分页查询订单列表，包含订单中的菜品数量、菜品名称、菜品图片。支持按订单编号或菜品名称搜索（限15字）")
    @GetMapping("/page")
    public R<IPage<StoreOrderPageVO>> getOrderPage(
            @ApiParam(value = "页码", required = true) @RequestParam(defaultValue = "1") Long current,
            @ApiParam(value = "每页数量", required = true) @RequestParam(defaultValue = "10") Long size,
            @ApiParam(value = "门店ID") @RequestParam(required = false) Integer storeId,
            @ApiParam(value = "桌号ID") @RequestParam(required = false) Integer tableId,
            @ApiParam(value = "订单状态：0=进行中（待支付+已支付），3=已完成") @RequestParam(required = false) Integer orderStatus,
            @ApiParam(value = "搜索关键词（订单编号或菜品名称，限15字）") @RequestParam(required = false) String keyword) {
        log.info("StoreOrderController.getOrderPage?current={}, size={}, storeId={}, tableId={}, orderStatus={}, keyword={}", current, size, storeId, tableId, orderStatus, keyword);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            Page<StoreOrder> page = new Page<>(current, size);
            IPage<StoreOrderPageVO> result = orderService.getOrderPageWithCuisines(page, storeId, tableId, orderStatus, keyword);
            return R.data(result);
        } catch (Exception e) {
            log.error("分页查询订单列表失败: {}", e.getMessage(), e);
            return R.fail("分页查询订单列表失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "查询我的订单", notes = "通过标识查询我的未支付订单或历史订单，包含订单中的菜品数量、菜品名称、菜品图片。type: 0或unpaid-未支付订单, 1或history-历史订单")
    @GetMapping("/my-orders")
    public R<IPage<StoreOrderPageVO>> getMyOrders(
            @ApiParam(value = "页码", required = true) @RequestParam(defaultValue = "1") Long current,
            @ApiParam(value = "每页数量", required = true) @RequestParam(defaultValue = "10") Long size,
            @ApiParam(value = "订单类型（0或unpaid:未支付订单, 1或history:历史订单）", required = true) @RequestParam String type) {
        log.info("StoreOrderController.getMyOrders?current={}, size={}, type={}", current, size, type);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            Page<StoreOrder> page = new Page<>(current, size);
            IPage<StoreOrderPageVO> result = orderService.getMyOrdersWithCuisines(page, type);
            return R.data(result);
        } catch (Exception e) {
            log.error("查询我的订单失败: {}", e.getMessage(), e);
            return R.fail("查询我的订单失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "换桌", notes = "换桌并迁移购物车、未完成的订单以及其他关联表数据")
    @PostMapping("/change-table")
    public R<CartDTO> changeTable(@Valid @RequestBody ChangeTableDTO dto) {
        log.info("StoreOrderController.changeTable?dto={}", dto);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }

            // 调用Service层处理换桌业务逻辑
            CartDTO cart = orderService.changeTable(dto.getFromTableId(), dto.getToTableId(), dto.getChangeReason(), userId);

            return R.data(cart);
        } catch (Exception e) {
            log.error("换桌失败: {}", e.getMessage(), e);
            return R.fail("换桌失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "建立SSE连接", notes = "建立SSE连接，用于接收购物车更新消息")
    @GetMapping(value = "/sse/{tableId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter createSseConnection(@ApiParam(value = "桌号ID", required = true) @PathVariable Integer tableId) {
        // 验证 token
        if (!TokenUtil.hasValidToken()) {
            log.warn("建立SSE连接失败: 用户未登录, tableId={}", tableId);
            return null;
        }
        log.info("建立SSE连接, tableId={}", tableId);
        return sseService.createConnection(tableId);
    }

    @ApiOperation(value = "完成订单", notes = "完成订单，将已支付状态的订单改为已完成状态。订单状态：0-待支付，1-已支付，3-已完成。只有已支付状态的订单才能完成")
    @PostMapping("/complete/{orderId}")
    public R<Boolean> completeOrder(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
        log.info("StoreOrderController.completeOrder?orderId={}", orderId);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            boolean result = orderService.completeOrder(orderId);
            return R.data(result);
        } catch (Exception e) {
            log.error("完成订单失败: {}", e.getMessage(), e);
            return R.fail("完成订单失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "商家手动完成订单", notes = "供商家使用，手动点击完成订单。不校验订单是否处于已支付状态，直接将订单状态改为已完成。订单状态：0-待支付，1-已支付，2-已取消，3-已完成")
    @PostMapping("/complete-by-merchant/{orderId}")
    public R<Boolean> completeOrderByMerchant(@ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
        log.info("StoreOrderController.completeOrderByMerchant?orderId={}", orderId);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            boolean result = orderService.completeOrderByMerchant(orderId);
            return R.data(result);
        } catch (Exception e) {
            log.error("商家手动完成订单失败: {}", e.getMessage(), e);
            return R.fail("商家手动完成订单失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "更新订单优惠券", notes = "重新选择优惠券")
    @PostMapping("/update-coupon")
    public R<StoreOrder> updateOrderCoupon(@Valid @RequestBody shop.alien.entity.store.dto.UpdateOrderCouponDTO dto) {
        log.info("StoreOrderController.updateOrderCoupon?dto={}", dto);
        try {
            // 从 token 获取用户信息
            Integer userId = TokenUtil.getCurrentUserId();
            if (userId == null) {
                return R.fail("用户未登录");
            }
            StoreOrder order = orderService.updateOrderCoupon(dto.getOrderId(), dto.getCouponId());
            return R.data(order);
        } catch (Exception e) {
            log.error("更新订单优惠券失败: {}", e.getMessage(), e);
            return R.fail("更新订单优惠券失败: " + e.getMessage());
        }
    }

    @ApiOperation(value = "管理员重置餐桌", notes = "管理员重置餐桌：删除购物车数据、未支付/已取消的订单数据，并重置餐桌表初始化。已支付/已完成的订单会被保留，避免数据丢失")
    @PostMapping("/admin/reset-table/{tableId}")
    public R<Boolean> resetTable(@ApiParam(value = "餐桌ID", required = true) @PathVariable Integer tableId) {
        log.info("StoreOrderController.resetTable?tableId={}", tableId);
        try {
            // TODO: 这里可以添加管理员权限验证
            // if (!isAdmin(userId)) {
            //     return R.fail("无权限执行此操作");
            // }
            
            boolean result = orderService.resetTable(tableId);
            if (result) {
                // 推送购物车更新消息（清空购物车）
                CartDTO emptyCart = new CartDTO();
                emptyCart.setTableId(tableId);
                emptyCart.setItems(java.util.Collections.emptyList());
                emptyCart.setTotalAmount(java.math.BigDecimal.ZERO);
                emptyCart.setTotalQuantity(0);
                
                // 查询桌号信息
                StoreTable table = storeTableMapper.selectById(tableId);
                if (table != null) {
                    emptyCart.setTableNumber(table.getTableNumber());
                    emptyCart.setStoreId(table.getStoreId());
                }
                
                sseService.pushCartUpdate(tableId, emptyCart);
                return R.data(true);
            } else {
                return R.fail("重置餐桌失败");
            }
        } catch (Exception e) {
            log.error("重置餐桌失败: {}", e.getMessage(), e);
            return R.fail("重置餐桌失败: " + e.getMessage());
        }
    }
}
