const express = require("express"); const router = express.Router(); const { pool } = require("../config/database"); const logger = require("../config/logger"); // Middleware to check customer auth from session const requireCustomerAuth = (req, res, next) => { if (!req.session || !req.session.customerId) { return res .status(401) .json({ success: false, message: "Please login to continue" }); } next(); }; // =========================== // CART ROUTES // =========================== // Get cart items router.get("/cart", requireCustomerAuth, async (req, res) => { try { const result = await pool.query( `SELECT cc.id, cc.product_id, cc.quantity, cc.variant_color, cc.variant_size, cc.added_at, p.name, p.price, p.imageurl, p.slug FROM customer_cart cc JOIN products p ON p.id = cc.product_id WHERE cc.customer_id = $1 ORDER BY cc.added_at DESC`, [req.session.customerId] ); const items = result.rows.map((row) => ({ id: row.id, productId: row.product_id, name: row.name, price: parseFloat(row.price), image: row.imageurl, slug: row.slug, quantity: row.quantity, variantColor: row.variant_color, variantSize: row.variant_size, addedAt: row.added_at, })); const total = items.reduce( (sum, item) => sum + item.price * item.quantity, 0 ); res.json({ success: true, items, itemCount: items.length, total: total.toFixed(2), }); } catch (error) { logger.error("Get cart error:", error); res.status(500).json({ success: false, message: "Failed to get cart" }); } }); // Add to cart router.post("/cart", requireCustomerAuth, async (req, res) => { try { const { productId, quantity = 1, variantColor, variantSize } = req.body; if (!productId) { return res .status(400) .json({ success: false, message: "Product ID is required" }); } // Check if product exists const productCheck = await pool.query( "SELECT id, name FROM products WHERE id = $1", [productId] ); if (productCheck.rows.length === 0) { return res .status(404) .json({ success: false, message: "Product not found" }); } // Insert or update cart item const result = await pool.query( `INSERT INTO customer_cart (customer_id, product_id, quantity, variant_color, variant_size) VALUES ($1, $2, $3, $4, $5) ON CONFLICT (customer_id, product_id, variant_color, variant_size) DO UPDATE SET quantity = customer_cart.quantity + EXCLUDED.quantity, updated_at = CURRENT_TIMESTAMP RETURNING id`, [ req.session.customerId, productId, quantity, variantColor || null, variantSize || null, ] ); logger.info( `Cart item added for customer ${req.session.customerId}: ${productId}` ); res.json({ success: true, message: "Added to cart", cartItemId: result.rows[0].id, }); } catch (error) { logger.error("Add to cart error:", error); res.status(500).json({ success: false, message: "Failed to add to cart" }); } }); // Update cart quantity router.put("/cart/:id", requireCustomerAuth, async (req, res) => { try { const { quantity } = req.body; if (!quantity || quantity < 1) { return res .status(400) .json({ success: false, message: "Quantity must be at least 1" }); } const result = await pool.query( `UPDATE customer_cart SET quantity = $1, updated_at = CURRENT_TIMESTAMP WHERE id = $2 AND customer_id = $3 RETURNING id`, [quantity, req.params.id, req.session.customerId] ); if (result.rows.length === 0) { return res .status(404) .json({ success: false, message: "Cart item not found" }); } res.json({ success: true, message: "Cart updated" }); } catch (error) { logger.error("Update cart error:", error); res.status(500).json({ success: false, message: "Failed to update cart" }); } }); // Remove from cart router.delete("/cart/:id", requireCustomerAuth, async (req, res) => { try { const result = await pool.query( "DELETE FROM customer_cart WHERE id = $1 AND customer_id = $2 RETURNING id", [req.params.id, req.session.customerId] ); if (result.rows.length === 0) { return res .status(404) .json({ success: false, message: "Cart item not found" }); } res.json({ success: true, message: "Removed from cart" }); } catch (error) { logger.error("Remove from cart error:", error); res .status(500) .json({ success: false, message: "Failed to remove from cart" }); } }); // Clear cart router.delete("/cart", requireCustomerAuth, async (req, res) => { try { await pool.query("DELETE FROM customer_cart WHERE customer_id = $1", [ req.session.customerId, ]); res.json({ success: true, message: "Cart cleared" }); } catch (error) { logger.error("Clear cart error:", error); res.status(500).json({ success: false, message: "Failed to clear cart" }); } }); // =========================== // WISHLIST ROUTES // =========================== // Get wishlist items router.get("/wishlist", requireCustomerAuth, async (req, res) => { try { const result = await pool.query( `SELECT cw.id, cw.product_id, cw.added_at, p.name, p.price, p.imageurl, p.slug FROM customer_wishlist cw JOIN products p ON p.id = cw.product_id WHERE cw.customer_id = $1 ORDER BY cw.added_at DESC`, [req.session.customerId] ); const items = result.rows.map((row) => ({ id: row.id, productId: row.product_id, name: row.name, price: parseFloat(row.price), image: row.imageurl, slug: row.slug, addedAt: row.added_at, })); res.json({ success: true, items, itemCount: items.length, }); } catch (error) { logger.error("Get wishlist error:", error); res.status(500).json({ success: false, message: "Failed to get wishlist" }); } }); // Add to wishlist router.post("/wishlist", requireCustomerAuth, async (req, res) => { try { const { productId } = req.body; if (!productId) { return res .status(400) .json({ success: false, message: "Product ID is required" }); } // Check if product exists const productCheck = await pool.query( "SELECT id, name FROM products WHERE id = $1", [productId] ); if (productCheck.rows.length === 0) { return res .status(404) .json({ success: false, message: "Product not found" }); } // Insert wishlist item (ignore if already exists) await pool.query( `INSERT INTO customer_wishlist (customer_id, product_id) VALUES ($1, $2) ON CONFLICT (customer_id, product_id) DO NOTHING`, [req.session.customerId, productId] ); logger.info( `Wishlist item added for customer ${req.session.customerId}: ${productId}` ); res.json({ success: true, message: "Added to wishlist" }); } catch (error) { logger.error("Add to wishlist error:", error); res .status(500) .json({ success: false, message: "Failed to add to wishlist" }); } }); // Remove from wishlist router.delete("/wishlist/:id", requireCustomerAuth, async (req, res) => { try { const result = await pool.query( "DELETE FROM customer_wishlist WHERE id = $1 AND customer_id = $2 RETURNING id", [req.params.id, req.session.customerId] ); if (result.rows.length === 0) { return res .status(404) .json({ success: false, message: "Wishlist item not found" }); } res.json({ success: true, message: "Removed from wishlist" }); } catch (error) { logger.error("Remove from wishlist error:", error); res .status(500) .json({ success: false, message: "Failed to remove from wishlist" }); } }); // Remove from wishlist by product ID router.delete( "/wishlist/product/:productId", requireCustomerAuth, async (req, res) => { try { await pool.query( "DELETE FROM customer_wishlist WHERE product_id = $1 AND customer_id = $2", [req.params.productId, req.session.customerId] ); res.json({ success: true, message: "Removed from wishlist" }); } catch (error) { logger.error("Remove from wishlist error:", error); res .status(500) .json({ success: false, message: "Failed to remove from wishlist" }); } } ); // Check if product is in wishlist router.get( "/wishlist/check/:productId", requireCustomerAuth, async (req, res) => { try { const result = await pool.query( "SELECT id FROM customer_wishlist WHERE product_id = $1 AND customer_id = $2", [req.params.productId, req.session.customerId] ); res.json({ success: true, inWishlist: result.rows.length > 0, wishlistItemId: result.rows[0]?.id || null, }); } catch (error) { logger.error("Check wishlist error:", error); res .status(500) .json({ success: false, message: "Failed to check wishlist" }); } } ); // Get cart count (for navbar badge) router.get("/cart/count", async (req, res) => { try { if (!req.session || !req.session.customerId) { return res.json({ success: true, count: 0 }); } const result = await pool.query( "SELECT COALESCE(SUM(quantity), 0) as count FROM customer_cart WHERE customer_id = $1", [req.session.customerId] ); res.json({ success: true, count: parseInt(result.rows[0].count), }); } catch (error) { logger.error("Get cart count error:", error); res.json({ success: true, count: 0 }); } }); // Get wishlist count (for navbar badge) router.get("/wishlist/count", async (req, res) => { try { if (!req.session || !req.session.customerId) { return res.json({ success: true, count: 0 }); } const result = await pool.query( "SELECT COUNT(*) as count FROM customer_wishlist WHERE customer_id = $1", [req.session.customerId] ); res.json({ success: true, count: parseInt(result.rows[0].count), }); } catch (error) { logger.error("Get wishlist count error:", error); res.json({ success: true, count: 0 }); } }); module.exports = router;