const express = require('express');
const { v4: uuidv4 } = require('uuid');
const router = express.Router();
const shippingService = require('../services/shippingService.js');
const config = require('../config');

module.exports = (pool, query, authMiddleware) => {

  router.use(authMiddleware);

  // Get user's cart
  router.get('/:userId', async (req, res, next) => {
    try {
      const { userId } = req.params;
      if (req.user.id !== userId) {
        return res.status(403).json({
          error: true,
          message: 'You can only access your own cart'
        });
      }
      // Get cart
      let cartResult = await query(
        'SELECT * FROM carts WHERE user_id = $1',
        [userId]
      );
      
      // If no cart exists, create one
      if (cartResult.rows.length === 0) {
        cartResult = await query(
          'INSERT INTO carts (id, user_id) VALUES ($1, $2) RETURNING *',
          [uuidv4(), userId]
        );
      }
      
      const cartId = cartResult.rows[0].id;
      
      // Get cart items with product details
      const cartItemsResult = await query(
        `SELECT ci.id, ci.quantity, ci.added_at, 
         p.id AS product_id, p.name, p.description, p.price,
         p.category_id, pc.name AS category_name,
         p.weight_grams, p.length_cm, p.width_cm, p.height_cm,
         (
           SELECT json_agg(
             json_build_object(
               'id', pi.id,
               'path', pi.image_path,
               'isPrimary', pi.is_primary,
               'displayOrder', pi.display_order
             ) ORDER BY pi.display_order
           )
           FROM product_images pi
           WHERE pi.product_id = p.id
         ) AS images
         FROM cart_items ci
         JOIN products p ON ci.product_id = p.id
         JOIN product_categories pc ON p.category_id = pc.id
         WHERE ci.cart_id = $1
         GROUP BY ci.id, ci.quantity, ci.added_at, p.id, p.name, p.description, p.price, p.category_id, pc.name, p.weight_grams, p.length_cm, p.width_cm, p.height_cm`,
        [cartId]
      );
      
      // Process images to add primary_image field
      const processedItems = cartItemsResult.rows.map(item => {
        // Add primary_image field derived from images array
        let primaryImage = null;
        if (item.images && item.images.length > 0) {
          primaryImage = item.images.find(img => img.isPrimary === true) || item.images[0];
        }
        
        return {
          ...item,
          primary_image: primaryImage
        };
      });
      
      // Calculate total
      const subtotal = processedItems.reduce((sum, item) => {
        return sum + (parseFloat(item.price) * item.quantity);
      }, 0);
      
      // Initialize shipping
      const shipping = {
        rates: []
      };
      
      // Calculate basic flat rate shipping
      if (config.shipping.enabled) {
        shipping.rates = await shippingService.getFlatRateShipping(subtotal);
      }
      
      res.json({
        id: cartId,
        userId,
        items: processedItems,
        itemCount: processedItems.length,
        subtotal,
        shipping,
        total: subtotal + (shipping.rates.length > 0 ? shipping.rates[0].rate : 0)
      });
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * Apply coupon to cart
   * POST /api/cart/apply-coupon
   */
  router.post('/apply-coupon', async (req, res, next) => {
    try {
      const { userId, code } = req.body;
      
      if (req.user.id !== userId) {
        return res.status(403).json({
          error: true,
          message: 'You can only modify your own cart'
        });
      }
      
      // Get cart
      const cartResult = await query(
        'SELECT * FROM carts WHERE user_id = $1',
        [userId]
      );
      
      if (cartResult.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Cart not found'
        });
      }
      
      const cartId = cartResult.rows[0].id;
      
      // Check if coupon code exists and is valid
      const couponResult = await query(`
        SELECT *
        FROM coupons
        WHERE code = $1 AND is_active = true
      `, [code.toUpperCase()]);
      
      if (couponResult.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Invalid coupon code or coupon is inactive'
        });
      }
      
      const coupon = couponResult.rows[0];
      
      // Check if coupon is expired
      if (coupon.end_date && new Date(coupon.end_date) < new Date()) {
        return res.status(400).json({
          error: true,
          message: 'Coupon has expired'
        });
      }
      
      // Check if coupon has not started yet
      if (coupon.start_date && new Date(coupon.start_date) > new Date()) {
        return res.status(400).json({
          error: true,
          message: 'Coupon is not yet active'
        });
      }
      
      // Check redemption limit
      if (coupon.redemption_limit !== null && coupon.current_redemptions >= coupon.redemption_limit) {
        return res.status(400).json({
          error: true,
          message: 'Coupon redemption limit has been reached'
        });
      }
      
      // Get cart items with product details
      const cartItems = await query(`
        SELECT ci.*, p.id as product_id, p.name, p.price, p.category_id, 
              pc.name as category_name,
              (
                SELECT array_agg(t.id)
                FROM product_tags pt
                JOIN tags t ON pt.tag_id = t.id
                WHERE pt.product_id = p.id
              ) as tag_ids
        FROM cart_items ci
        JOIN products p ON ci.product_id = p.id
        JOIN product_categories pc ON p.category_id = pc.id
        WHERE ci.cart_id = $1
      `, [cartId]);
      
      if (cartItems.rows.length === 0) {
        return res.status(400).json({
          error: true,
          message: 'Cart is empty'
        });
      }
      
      // Calculate subtotal
      const subtotal = cartItems.rows.reduce((sum, item) => {
        return sum + (parseFloat(item.price) * item.quantity);
      }, 0);
      
      // Check minimum purchase requirement
      if (coupon.min_purchase_amount && subtotal < coupon.min_purchase_amount) {
        return res.status(400).json({
          error: true,
          message: `Minimum purchase amount of ${coupon.min_purchase_amount.toFixed(2)} not met`,
          minimumAmount: coupon.min_purchase_amount
        });
      }
      
      // Get coupon categories
      const couponCategories = await query(`
        SELECT category_id
        FROM coupon_categories
        WHERE coupon_id = $1
      `, [coupon.id]);
      
      // Get coupon tags
      const couponTags = await query(`
        SELECT tag_id
        FROM coupon_tags
        WHERE coupon_id = $1
      `, [coupon.id]);
      
      // Get blacklisted products
      const blacklistResult = await query(`
        SELECT product_id
        FROM coupon_blacklist
        WHERE coupon_id = $1
      `, [coupon.id]);
      
      const blacklistedProductIds = blacklistResult.rows.map(row => row.product_id);
      
      // Calculate discount based on eligible products
      let discountableAmount = 0;
      
      const categoryIds = couponCategories.rows.map(row => row.category_id);
      const tagIds = couponTags.rows.map(row => row.tag_id);
      
      for (const item of cartItems.rows) {
        // Skip blacklisted products
        if (blacklistedProductIds.includes(item.product_id)) {
          continue;
        }
        
        let isEligible = false;
        
        // If no categories or tags are specified, all products are eligible
        if (categoryIds.length === 0 && tagIds.length === 0) {
          isEligible = true;
        } else {
          // Check if product belongs to eligible category
          if (categoryIds.includes(item.category_id)) {
            isEligible = true;
          }
          
          // Check if product has eligible tag
          if (!isEligible && item.tag_ids && item.tag_ids.some(tagId => tagIds.includes(tagId))) {
            isEligible = true;
          }
        }
        
        if (isEligible) {
          discountableAmount += parseFloat(item.price) * item.quantity;
        }
      }
      
      // Calculate discount amount
      let discountAmount = 0;
      if (coupon.discount_type === 'percentage') {
        discountAmount = discountableAmount * (coupon.discount_value / 100);
      } else { // fixed_amount
        discountAmount = Math.min(discountableAmount, coupon.discount_value);
      }
      
      // Apply maximum discount cap if set
      if (coupon.max_discount_amount && discountAmount > coupon.max_discount_amount) {
        discountAmount = coupon.max_discount_amount;
      }
      
      // Round to 2 decimal places
      discountAmount = Math.round(discountAmount * 100) / 100;
      
      // Update cart metadata with coupon information
      await query(`
        UPDATE carts
        SET metadata = jsonb_set(
          COALESCE(metadata, '{}'::jsonb),
          '{coupon}',
          $1::jsonb
        )
        WHERE id = $2
      `, [
        JSON.stringify({
          id: coupon.id,
          code: coupon.code,
          discount_type: coupon.discount_type,
          discount_value: coupon.discount_value,
          discount_amount: discountAmount
        }),
        cartId
      ]);
      
      // Get updated cart with all items
      const updatedCartItems = await query(`
        SELECT ci.*, p.id AS product_id, p.name, p.description, p.price, p.stock_quantity,
        p.category_id, pc.name AS category_name,
        p.weight_grams, p.length_cm, p.width_cm, p.height_cm,
        (
          SELECT json_agg(
            json_build_object(
              'id', pi.id,
              'path', pi.image_path,
              'isPrimary', pi.is_primary,
              'displayOrder', pi.display_order
            ) ORDER BY pi.display_order
          )
          FROM product_images pi
          WHERE pi.product_id = p.id
        ) AS images
        FROM cart_items ci
        JOIN products p ON ci.product_id = p.id
        JOIN product_categories pc ON p.category_id = pc.id
        WHERE ci.cart_id = $1
        GROUP BY ci.id, ci.quantity, ci.added_at, p.id, p.name, p.description, p.price, 
        p.stock_quantity, p.category_id, pc.name, p.weight_grams, p.length_cm, p.width_cm, p.height_cm
      `, [cartId]);
      
      // Get cart metadata with coupon
      const cartMetadata = await query(`
        SELECT metadata
        FROM carts
        WHERE id = $1
      `, [cartId]);
      
      // Process images to add primary_image field
      const processedItems = updatedCartItems.rows.map(item => {
        // Add primary_image field derived from images array
        let primaryImage = null;
        if (item.images && item.images.length > 0) {
          primaryImage = item.images.find(img => img.isPrimary === true) || item.images[0];
        }
        
        return {
          ...item,
          primary_image: primaryImage
        };
      });
      
      // Calculate subtotal
      const cartSubtotal = processedItems.reduce((sum, item) => {
        return sum + (parseFloat(item.price) * item.quantity);
      }, 0);
      
      // Calculate total with discount
      const total = cartSubtotal - discountAmount;
      
      // Format coupon info for response
      const couponInfo = cartMetadata.rows[0].metadata.coupon;
      
      res.json({
        id: cartId,
        userId,
        items: processedItems,
        itemCount: processedItems.length,
        subtotal: cartSubtotal,
        couponDiscount: discountAmount,
        couponCode: couponInfo.code,
        couponId: couponInfo.id,
        total: total
      });
    } catch (error) {
      next(error);
    }
  });

  /**
   * Remove coupon from cart
   * POST /api/cart/remove-coupon
   */
  router.post('/remove-coupon', async (req, res, next) => {
    try {
      const { userId } = req.body;
      
      if (req.user.id !== userId) {
        return res.status(403).json({
          error: true,
          message: 'You can only modify your own cart'
        });
      }
      
      // Get cart
      const cartResult = await query(
        'SELECT * FROM carts WHERE user_id = $1',
        [userId]
      );
      
      if (cartResult.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Cart not found'
        });
      }
      
      const cartId = cartResult.rows[0].id;
      
      // Remove coupon from cart metadata
      await query(`
        UPDATE carts
        SET metadata = metadata - 'coupon'
        WHERE id = $1
      `, [cartId]);
      
      // Get updated cart with all items
      const updatedCartItems = await query(`
        SELECT ci.*, p.id AS product_id, p.name, p.description, p.price, p.stock_quantity,
        p.category_id, pc.name AS category_name,
        p.weight_grams, p.length_cm, p.width_cm, p.height_cm,
        (
          SELECT json_agg(
            json_build_object(
              'id', pi.id,
              'path', pi.image_path,
              'isPrimary', pi.is_primary,
              'displayOrder', pi.display_order
            ) ORDER BY pi.display_order
          )
          FROM product_images pi
          WHERE pi.product_id = p.id
        ) AS images
        FROM cart_items ci
        JOIN products p ON ci.product_id = p.id
        JOIN product_categories pc ON p.category_id = pc.id
        WHERE ci.cart_id = $1
        GROUP BY ci.id, ci.quantity, ci.added_at, p.id, p.name, p.description, p.price, 
        p.stock_quantity, p.category_id, pc.name, p.weight_grams, p.length_cm, p.width_cm, p.height_cm
      `, [cartId]);
      
      // Process images to add primary_image field
      const processedItems = updatedCartItems.rows.map(item => {
        // Add primary_image field derived from images array
        let primaryImage = null;
        if (item.images && item.images.length > 0) {
          primaryImage = item.images.find(img => img.isPrimary === true) || item.images[0];
        }
        
        return {
          ...item,
          primary_image: primaryImage
        };
      });
      
      // Calculate subtotal
      const subtotal = processedItems.reduce((sum, item) => {
        return sum + (parseFloat(item.price) * item.quantity);
      }, 0);
      
      res.json({
        id: cartId,
        userId,
        items: processedItems,
        itemCount: processedItems.length,
        subtotal,
        total: subtotal,
        message: 'Coupon removed successfully'
      });
    } catch (error) {
      next(error);
    }
  });
     
  
  // Add item to cart
  router.post('/add', async (req, res, next) => {
    try {
      const { userId, productId, quantity = 1 } = req.body;
      if (req.user.id !== userId) {
        return res.status(403).json({
          error: true,
          message: 'You can only modify your own cart'
        });
      }
      // Check if product exists and verify stock
      const productResult = await query(
        'SELECT id, name, stock_quantity FROM products WHERE id = $1',
        [productId]
      );
      
      if (productResult.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Product not found'
        });
      }
      
      const product = productResult.rows[0];
      
      // Get or create cart
      let cartResult = await query(
        'SELECT * FROM carts WHERE user_id = $1',
        [userId]
      );
      
      if (cartResult.rows.length === 0) {
        cartResult = await query(
          'INSERT INTO carts (id, user_id) VALUES ($1, $2) RETURNING *',
          [uuidv4(), userId]
        );
      }
      
      const cartId = cartResult.rows[0].id;
      
      // Check if item already in cart
      const existingItemResult = await query(
        'SELECT * FROM cart_items WHERE cart_id = $1 AND product_id = $2',
        [cartId, productId]
      );
      
      let newQuantity = quantity;
      
      if (existingItemResult.rows.length > 0) {
        // If item already exists, calculate new total quantity
        newQuantity = existingItemResult.rows[0].quantity + quantity;
      }
      
      if (quantity < 1) {
        return res.status(400).json({
          error: true,
          message: `Insufficient quantity requested. Only ${product.stock_quantity} units of "${product.name}" are available.`,
          availableQuantity: product.stock_quantity,
          currentCartQuantity: existingItemResult.rows.length > 0 ? existingItemResult.rows[0].quantity : 0
        });
      }
      
      // Verify the total requested quantity is available in stock
      if (newQuantity > product.stock_quantity) {
        return res.status(400).json({
          error: true,
          message: `Insufficient stock. Only ${product.stock_quantity} units of "${product.name}" are available.`,
          availableQuantity: product.stock_quantity,
          currentCartQuantity: existingItemResult.rows.length > 0 ? existingItemResult.rows[0].quantity : 0
        });
      }
      
      if (existingItemResult.rows.length > 0) {
        // Update quantity
        await query(
          'UPDATE cart_items SET quantity = $1 WHERE id = $2',
          [newQuantity, existingItemResult.rows[0].id]
        );
      } else {
        // Add new item
        await query(
          'INSERT INTO cart_items (id, cart_id, product_id, quantity) VALUES ($1, $2, $3, $4)',
          [uuidv4(), cartId, productId, quantity]
        );
      }
      
      // Get updated cart
      const updatedCartItems = await query(
        `SELECT ci.id, ci.quantity, ci.added_at, 
        p.id AS product_id, p.name, p.description, p.price, p.stock_quantity,
        p.category_id, pc.name AS category_name,
        p.weight_grams, p.length_cm, p.width_cm, p.height_cm,
        (
          SELECT json_agg(
            json_build_object(
              'id', pi.id,
              'path', pi.image_path,
              'isPrimary', pi.is_primary,
              'displayOrder', pi.display_order
            ) ORDER BY pi.display_order
          )
          FROM product_images pi
          WHERE pi.product_id = p.id
        ) AS images
        FROM cart_items ci
        JOIN products p ON ci.product_id = p.id
        JOIN product_categories pc ON p.category_id = pc.id
        WHERE ci.cart_id = $1
        GROUP BY ci.id, ci.quantity, ci.added_at, p.id, p.name, p.description, p.price, p.stock_quantity, p.category_id, pc.name, p.weight_grams, p.length_cm, p.width_cm, p.height_cm`,
        [cartId]
      );
      
      // Process images to add primary_image field
      const processedItems = updatedCartItems.rows.map(item => {
        // Add primary_image field derived from images array
        let primaryImage = null;
        if (item.images && item.images.length > 0) {
          primaryImage = item.images.find(img => img.isPrimary === true) || item.images[0];
        }
        
        return {
          ...item,
          primary_image: primaryImage
        };
      });
      
      // Calculate subtotal
      const subtotal = processedItems.reduce((sum, item) => {
        return sum + (parseFloat(item.price) * item.quantity);
      }, 0);
      
      // Initialize shipping
      const shipping = {
        rates: []
      };
      
      // Calculate basic flat rate shipping
      if (config.shipping.enabled) {
        shipping.rates = await shippingService.getFlatRateShipping(subtotal);
      }
      
      res.json({
        id: cartId,
        userId,
        items: processedItems,
        itemCount: processedItems.length,
        subtotal,
        shipping,
        total: subtotal + (shipping.rates.length > 0 ? shipping.rates[0].rate : 0)
      });
    } catch (error) {
      next(error);
    }
  });
  
  // Update cart item quantity
  router.put('/update', async (req, res, next) => {
    try {
      const { userId, productId, quantity } = req.body;
      if (req.user.id !== userId) {
        return res.status(403).json({
          error: true,
          message: 'You can only modify your own cart'
        });
      }
      
      // Get cart
      const cartResult = await query(
        'SELECT * FROM carts WHERE user_id = $1',
        [userId]
      );
      
      if (cartResult.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Cart not found'
        });
      }
      
      const cartId = cartResult.rows[0].id;
      
      if (quantity <= 0) {
        // Remove item
        await query(
          'DELETE FROM cart_items WHERE cart_id = $1 AND product_id = $2',
          [cartId, productId]
        );
      } else {
        // Check product availability before updating
        const productResult = await query(
          'SELECT id, name, stock_quantity FROM products WHERE id = $1',
          [productId]
        );
        
        if (productResult.rows.length === 0) {
          return res.status(404).json({
            error: true,
            message: 'Product not found'
          });
        }
        
        const product = productResult.rows[0];
        
        // Verify the requested quantity is available in stock
        if (quantity > product.stock_quantity) {
          return res.status(400).json({
            error: true,
            message: `Insufficient stock. Only ${product.stock_quantity} units of "${product.name}" are available.`,
            availableQuantity: product.stock_quantity
          });
        }
        
        // Update quantity if stock is sufficient
        await query(
          'UPDATE cart_items SET quantity = $1 WHERE cart_id = $2 AND product_id = $3',
          [quantity, cartId, productId]
        );
      }
      
      // Get updated cart
      const updatedCartItems = await query(
        `SELECT ci.id, ci.quantity, ci.added_at, 
        p.id AS product_id, p.name, p.description, p.price, p.stock_quantity,
        p.category_id, pc.name AS category_name,
        p.weight_grams, p.length_cm, p.width_cm, p.height_cm,
        (
          SELECT json_agg(
            json_build_object(
              'id', pi.id,
              'path', pi.image_path,
              'isPrimary', pi.is_primary,
              'displayOrder', pi.display_order
            ) ORDER BY pi.display_order
          )
          FROM product_images pi
          WHERE pi.product_id = p.id
        ) AS images
        FROM cart_items ci
        JOIN products p ON ci.product_id = p.id
        JOIN product_categories pc ON p.category_id = pc.id
        WHERE ci.cart_id = $1
        GROUP BY ci.id, ci.quantity, ci.added_at, p.id, p.name, p.description, p.price, p.stock_quantity, p.category_id, pc.name, p.weight_grams, p.length_cm, p.width_cm, p.height_cm`,
        [cartId]
      );
      
      // Process images to add primary_image field
      const processedItems = updatedCartItems.rows.map(item => {
        // Add primary_image field derived from images array
        let primaryImage = null;
        if (item.images && item.images.length > 0) {
          primaryImage = item.images.find(img => img.isPrimary === true) || item.images[0];
        }
        
        return {
          ...item,
          primary_image: primaryImage
        };
      });
      
      // Calculate subtotal
      const subtotal = processedItems.reduce((sum, item) => {
        return sum + (parseFloat(item.price) * item.quantity);
      }, 0);
      
      // Initialize shipping
      const shipping = {
        rates: []
      };
      
      // Calculate basic flat rate shipping
      if (config.shipping.enabled) {
        shipping.rates = await shippingService.getFlatRateShipping(subtotal);
      }
      
      res.json({
        id: cartId,
        userId,
        items: processedItems,
        itemCount: processedItems.length,
        subtotal,
        shipping,
        total: subtotal + (shipping.rates.length > 0 ? shipping.rates[0].rate : 0)
      });
    } catch (error) {
      next(error);
    }
  });
  
  // Clear cart
  router.delete('/clear/:userId', async (req, res, next) => {
    try {
      const { userId } = req.params;
      if (req.user.id !== userId) {
        return res.status(403).json({
          error: true,
          message: 'You can only modify your own cart'
        });
      }
      // Get cart
      const cartResult = await query(
        'SELECT * FROM carts WHERE user_id = $1',
        [userId]
      );
      
      if (cartResult.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Cart not found'
        });
      }
      
      const cartId = cartResult.rows[0].id;
      
      // Delete all items
      await query(
        'DELETE FROM cart_items WHERE cart_id = $1',
        [cartId]
      );
      
      res.json({
        id: cartId,
        userId,
        items: [],
        itemCount: 0,
        subtotal: 0,
        shipping: {
          rates: []
        },
        total: 0
      });
    } catch (error) {
      next(error);
    }
  });
  
  // Get shipping rates for current cart
  router.post('/shipping-rates', async (req, res, next) => {
    try {
      const { userId, shippingAddress } = req.body;
      
      if (req.user.id !== userId) {
        return res.status(403).json({
          error: true,
          message: 'You can only get shipping rates for your own cart'
        });
      }
      
      // Shipping must be enabled
      if (!config.shipping.enabled) {
        return res.status(400).json({
          error: true,
          message: 'Shipping is currently disabled'
        });
      }
      
      // Get cart
      const cartResult = await query(
        'SELECT * FROM carts WHERE user_id = $1',
        [userId]
      );
      
      if (cartResult.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Cart not found'
        });
      }
      
      const cartId = cartResult.rows[0].id;
      
      // Get cart items with product weights
      const cartItemsResult = await query(
        `SELECT ci.quantity, p.id, p.weight_grams, p.price, 
         p.length_cm, p.width_cm, p.height_cm
         FROM cart_items ci
         JOIN products p ON ci.product_id = p.id
         WHERE ci.cart_id = $1`,
        [cartId]
      );
      
      if (cartItemsResult.rows.length === 0) {
        return res.status(400).json({
          error: true,
          message: 'Cart is empty'
        });
      }
      
      // Calculate total weight and order value
      const totalWeight = shippingService.calculateTotalWeight(cartItemsResult.rows);
      const subtotal = cartItemsResult.rows.reduce((sum, item) => {
        return sum + (parseFloat(item.price) * item.quantity);
      }, 0);
      
      // If no address provided, return only flat rate shipping
      if (!shippingAddress) {
        console.log("No Address provided - using flat rate");
        const rates = shippingService.getFlatRateShipping(subtotal);
        
        return res.json({
          success: true,
          shipment_id: null,
          rates
        });
      }
      
      // Get real shipping rates with a shipment
      const parsedAddress = typeof shippingAddress === 'string' 
        ? shippingService.parseAddressString(shippingAddress)
        : shippingAddress;
      
      
      const shippingResponse = await shippingService.getShippingRates(
        null, // Use default from config
        parsedAddress,
        {
          weight: totalWeight,
          length: Math.max(...cartItemsResult.rows.map(item => item.length_cm || 0)),
          width: Math.max(...cartItemsResult.rows.map(item => item.width_cm || 0)),
          height: Math.max(...cartItemsResult.rows.map(item => item.height_cm || 0)),
          order_total: subtotal
        }
      );
      
      console.log("Shipping rates response:", JSON.stringify(shippingResponse, null, 4));
      
      // Save the shipment ID to the session or temporary storage
      // This will be used when the user selects a rate
      if (shippingResponse.shipment_id) {
        // Store the shipment ID in the user's cart for later use
        await query(
          `UPDATE carts SET metadata = jsonb_set(
            COALESCE(metadata, '{}'::jsonb),
            '{temp_shipment_id}',
            $1::jsonb
          ) WHERE id = $2`,
          [JSON.stringify(shippingResponse.shipment_id), cartId]
        );
      }
      
      res.json({
        success: true,
        shipment_id: shippingResponse.shipment_id,
        rates: shippingResponse.rates
      });
    } catch (error) {
      console.error('Error getting shipping rates:', error);
      next(error);
    }
  });
  
  router.post('/checkout', async (req, res, next) => {
    try {
      const { userId, shippingAddress, shippingMethod } = req.body;
      
      if (req.user.id !== userId) {
        return res.status(403).json({
          error: true,
          message: 'You can only checkout your own cart'
        });
      }
      
      // Get cart
      const cartResult = await query(
        'SELECT * FROM carts WHERE user_id = $1',
        [userId]
      );
      
      if (cartResult.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Cart not found'
        });
      }
      
      const cartId = cartResult.rows[0].id;
      
      // Get cart items
      const cartItemsResult = await query(
        `SELECT ci.*, p.price, p.name, p.description, p.weight_grams, p.length_cm, p.width_cm, p.height_cm,
        (
          SELECT json_build_object(
            'path', pi.image_path,
            'isPrimary', pi.is_primary
          )
          FROM product_images pi
          WHERE pi.product_id = p.id AND pi.is_primary = true
          LIMIT 1
        ) AS primary_image
         FROM cart_items ci
         JOIN products p ON ci.product_id = p.id
         WHERE ci.cart_id = $1`,
        [cartId]
      );
      
      if (cartItemsResult.rows.length === 0) {
        return res.status(400).json({
          error: true,
          message: 'Cart is empty'
        });
      }
      
      // Calculate subtotal
      const subtotal = cartItemsResult.rows.reduce((sum, item) => {
        return sum + (parseFloat(item.price) * item.quantity);
      }, 0);
      
      // Determine shipping cost and create shipment if needed
      let shippingCost = 0;
      let shipmentData = null;
      
      if (config.shipping.enabled) {
        // If a specific shipping method was selected
        if (shippingMethod && shippingMethod.id) {
          shippingCost = parseFloat(shippingMethod.rate) || 0;
          
          // Check if this is a non-flat rate and we need to purchase a real shipment
          if (config.shipping.easypostEnabled && 
              !shippingMethod.id.includes('flat-rate') && 
              !shippingMethod.id.includes('free-shipping')) {
            
            try {
              // Parse shipping address to object if it's a string
              const parsedAddress = typeof shippingAddress === 'string' 
                ? shippingService.parseAddressString(shippingAddress)
                : shippingAddress;
                
              // Retrieve temporary shipment ID from cart metadata
              const cartMetadataResult = await query(
                'SELECT metadata FROM carts WHERE id = $1',
                [cartId]
              );
              
              let shipmentId = null;
              if (cartMetadataResult.rows.length > 0 && 
                  cartMetadataResult.rows[0].metadata && 
                  cartMetadataResult.rows[0].metadata.temp_shipment_id) {
                shipmentId = cartMetadataResult.rows[0].metadata.temp_shipment_id;
              }
              
              if (shipmentId) {
                // Purchase the shipment with the selected rate
                shipmentData = await shippingService.purchaseShipment(
                  shipmentId,
                  shippingMethod.id
                );
                
                console.log('Shipment purchased successfully:', shipmentData.shipment_id);
                
                // Use the actual rate from the purchased shipment
                shippingCost = shipmentData.selected_rate.rate;
              } else {
                console.log('No shipment ID found in cart metadata, using standard rate');
              }
            } catch (error) {
              console.error('Error purchasing shipment:', error);
              // Continue with the rate provided
            }
          }
        } else {
          // Default to flat rate if no method selected
          const shippingRates = shippingService.getFlatRateShipping(subtotal);
          shippingCost = shippingRates[0].rate;
        }
      }
      
      // Calculate total with shipping
      const total = subtotal + shippingCost;
      
      // Begin transaction
      const client = await pool.connect();
      
      try {
        await client.query('BEGIN');
        
        // Create order
        const orderId = uuidv4();
        await client.query(
          'INSERT INTO orders (id, user_id, status, total_amount, shipping_address, payment_completed, shipping_cost) VALUES ($1, $2, $3, $4, $5, $6, $7)',
          [orderId, userId, 'pending', total, shippingAddress, false, shippingCost]
        );
        
        // Create order items
        for (const item of cartItemsResult.rows) {
          await client.query(
            'INSERT INTO order_items (id, order_id, product_id, quantity, price_at_purchase) VALUES ($1, $2, $3, $4, $5)',
            [uuidv4(), orderId, item.product_id, item.quantity, item.price]
          );
        }
        
        // If we have shipping details, save them with the order
        if (shippingMethod && shippingMethod.id) {
          const shippingInfo = shipmentData || {
            method_id: shippingMethod.id,
            carrier: shippingMethod.carrier,
            service: shippingMethod.service,
            rate: shippingMethod.rate,
            estimated_days: shippingMethod.delivery_days,
            tracking_code: null
          };
          
          await client.query(
            'UPDATE orders SET shipping_info = $1 WHERE id = $2',
            [JSON.stringify(shippingInfo), orderId]
          );
        }
        
        // Clear the temporary shipment ID from cart metadata
        await client.query(
          `UPDATE carts SET metadata = metadata - 'temp_shipment_id' WHERE id = $1`,
          [cartId]
        );
        
        await client.query('COMMIT');
        
        // Send back cart items for Stripe checkout
        res.status(201).json({
          success: true,
          message: 'Order created successfully, ready for payment',
          orderId,
          cartItems: cartItemsResult.rows,
          subtotal,
          shippingCost,
          total,
          shipmentData
        });
        
        // Note: We don't clear the cart here now - we'll do that after successful payment
      } catch (error) {
        await client.query('ROLLBACK');
        throw error;
      } finally {
        client.release();
      }
    } catch (error) {
      next(error);
    }
  });
  
  //  Complete checkout after successful payment
  router.post('/complete-checkout', async (req, res, next) => {
    try {
      const { userId, orderId, sessionId } = req.body;
      console.log("Complete Checkout ", `${userId} ${orderId} ${sessionId}`)
      
      if (req.user.id !== userId) {
        return res.status(403).json({
          error: true,
          message: 'You can only complete your own checkout'
        });
      }
      
      // Verify the order exists and belongs to the user
      const orderResult = await query(
        'SELECT * FROM orders WHERE id = $1 AND user_id = $2',
        [orderId, userId]
      );
      
      if (orderResult.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Order not found'
        });
      }
      
      // Begin transaction
      const client = await pool.connect();
      
      try {
        await client.query('BEGIN');
        
        // Update order status and payment info
        await client.query(
          'UPDATE orders SET status = $1, payment_completed = true, payment_id = $2 WHERE id = $3',
          ['processing', sessionId, orderId]
        );
        
        // Get cart
        const cartResult = await client.query(
          'SELECT * FROM carts WHERE user_id = $1',
          [userId]
        );
        
        if (cartResult.rows.length > 0) {
          const cartId = cartResult.rows[0].id;
          
          // Get cart items to update product stock
          const cartItemsResult = await client.query(
            'SELECT * FROM cart_items WHERE cart_id = $1',
            [cartId]
          );
          
          // Update product stock
          for (const item of cartItemsResult.rows) {
            await client.query(
              'UPDATE products SET stock_quantity = stock_quantity - $1 WHERE id = $2',
              [item.quantity, item.product_id]
            );
            
            // Process stock notifications after updating stock
            try {
              const productWithNotification = await client.query(
                `SELECT id, name, stock_quantity, stock_notification 
                 FROM products 
                 WHERE id = $1`,
                [item.product_id]
              );
              
              if (productWithNotification.rows.length > 0) {
                const product = productWithNotification.rows[0];
                let stockNotification;
                
                // Handle different ways the JSON could be stored
                if (product.stock_notification) {
                  try {
                    // If it's a string, parse it
                    // why are we doing this its been an obj for months now
                    if (typeof product.stock_notification === 'string') {
                      stockNotification = JSON.parse(product.stock_notification);
                    } else {
                      // Otherwise use as is
                      stockNotification = product.stock_notification;
                    }
                    
                    console.log("Stock notification for product:", product.id, stockNotification);
                    
                    // Check if notification is enabled and stock is below threshold
                    if (stockNotification && 
                        stockNotification.enabled === true &&
                        stockNotification.email &&
                        stockNotification.threshold &&
                        product.stock_quantity <= parseInt(stockNotification.threshold)) {
                      
                      // Log the notification with the order ID
                      await client.query(
                        `INSERT INTO notification_logs 
                         (order_id, notification_type, sent_at, status) 
                         VALUES ($1, $2, NOW(), $3)`,
                        [orderId, 'low_stock_alert', 'pending']
                      );
                      
                      console.log(`Low stock notification queued for product ${product.id} - ${product.name}`);
                    }
                  } catch (parseError) {
                    console.error("Error parsing stock notification JSON:", parseError);
                  }
                }
              }
            } catch (notificationError) {
              console.error("Error processing stock notification:", notificationError);
              // Continue with checkout even if notification processing fails
            }
          }
          
          // Clear cart
          await client.query(
            'DELETE FROM cart_items WHERE cart_id = $1',
            [cartId]
          );
        }
        
        await client.query('COMMIT');
        
        res.status(200).json({
          success: true,
          message: 'Order completed successfully',
          orderId
        });
      } catch (error) {
        await client.query('ROLLBACK');
        throw error;
      } finally {
        client.release();
      }
    } catch (error) {
      next(error);
    }
  });
  
  return router;
};