const Cart = require('../models/Cart'); const Product = require('../models/Product'); const Coupon = require('../models/Coupon'); const { successResponse, errorResponse } = require('../utils/apiResponse'); const getCart = async (req, res, next) => { try { const userId = req.user ? req.user._id : null; const sessionId = req.headers['x-session-id'] || null; let cart = null; if (userId) { cart = await Cart.findOne({ user: userId }).populate('items.product'); } else if (sessionId) { cart = await Cart.findOne({ sessionId }).populate('items.product'); } if (!cart) { cart = { items: [], couponCode: '', discountAmount: 0 }; } return successResponse(res, 'Cart retrieved', cart); } catch (error) { next(error); } }; const addToCart = async (req, res, next) => { try { const { productId, quantity = 1, variantColor = '', variantFinish = '' } = req.body; const userId = req.user ? req.user._id : null; const sessionId = req.headers['x-session-id'] || 'guest-' + Date.now(); const product = await Product.findById(productId); if (!product) { return errorResponse(res, 'Product not found', [], 404); } // Inventory check if (product.stock < quantity) { return errorResponse(res, `Only ${product.stock} items remaining in stock`, [], 400); } let cart; if (userId) { cart = await Cart.findOne({ user: userId }); } else { cart = await Cart.findOne({ sessionId }); } const price = product.salePrice > 0 ? product.salePrice : product.price; if (!cart) { cart = new Cart({ user: userId, sessionId, items: [{ product: productId, quantity, variantColor, variantFinish, price }] }); } else { const existingItemIndex = cart.items.findIndex( item => item.product.toString() === productId && item.variantColor === variantColor ); if (existingItemIndex > -1) { cart.items[existingItemIndex].quantity += Number(quantity); } else { cart.items.push({ product: productId, quantity, variantColor, variantFinish, price }); } } await cart.save(); const updatedCart = await Cart.findById(cart._id).populate('items.product'); return successResponse(res, 'Product added to cart', updatedCart); } catch (error) { next(error); } }; const updateCartItem = async (req, res, next) => { try { const { itemId, quantity } = req.body; const userId = req.user ? req.user._id : null; const sessionId = req.headers['x-session-id']; const cart = userId ? await Cart.findOne({ user: userId }) : await Cart.findOne({ sessionId }); if (!cart) return errorResponse(res, 'Cart not found', [], 404); const item = cart.items.id(itemId); if (!item) return errorResponse(res, 'Item not found in cart', [], 404); if (quantity <= 0) { cart.items.pull(itemId); } else { item.quantity = quantity; } await cart.save(); const updatedCart = await Cart.findById(cart._id).populate('items.product'); return successResponse(res, 'Cart updated', updatedCart); } catch (error) { next(error); } }; const removeCartItem = async (req, res, next) => { try { const userId = req.user ? req.user._id : null; const sessionId = req.headers['x-session-id']; const cart = userId ? await Cart.findOne({ user: userId }) : await Cart.findOne({ sessionId }); if (cart) { cart.items = cart.items.filter(item => item._id.toString() !== req.params.itemId); await cart.save(); } const updatedCart = cart ? await Cart.findById(cart._id).populate('items.product') : { items: [] }; return successResponse(res, 'Item removed from cart', updatedCart); } catch (error) { next(error); } }; const applyCoupon = async (req, res, next) => { try { const { code } = req.body; const coupon = await Coupon.findOne({ code: code.toUpperCase(), isActive: true }); if (!coupon || coupon.endDate < new Date()) { return errorResponse(res, 'Invalid or expired coupon code', [], 400); } return successResponse(res, 'Coupon applied successfully', { code: coupon.code, discountType: coupon.discountType, discountValue: coupon.discountValue, minPurchaseAmount: coupon.minPurchaseAmount }); } catch (error) { next(error); } }; module.exports = { getCart, addToCart, updateCartItem, removeCartItem, applyCoupon };