const User = require("../models/User.js");
const Product = require("../models/Product.js");
const Order = require("../models/Order.js");
const auth = require("../auth.js");
const {verify, verifyAdmin} = auth;


// Controllers

// create product controller
module.exports.createProduct = async (req, res) => {
  try {
    const { name, price, description, inventory } = req.body;

    // Create a new product instance
    const product = new Product({
      name,
      price,
      description,
      inventory,
    });

    // Save the product to the database
    await product.save();

    res.status(201).json({ message: 'Product created successfully', product });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: 'Error creating product' });
  }
};


// retrieve all products controller
module.exports.getAllProducts = async (req, res) => {
  try {
    // Fetch all products from the database
    const products = await Product.find();

    res.json(products);
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: 'Error retrieving products' });
  }
};


// retrieve all active products controller
exports.getAllActiveProducts = async (req, res) => {
  try {
    const products = await Product.find({ isActive: true });

    res.json(products);
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: 'Error retrieving active products' });
  }
};


// search products controller
exports.searchProducts = async (req, res) => {
  try {
    const { query } = req.body;

    // Build the search query using case-insensitive regex
    const regex = new RegExp(escapeRegex(query), 'i');

    const products = await Product.find({
      $or: [
        { name: regex },
        // Add more fields to search if needed
      ],
    });

    res.json(products);
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: 'Error searching products' });
  }
};


// Helper function to escape special characters in the search query
function escapeRegex(text) {
  return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}


// update product controller
exports.updateProduct = async (req, res) => {
  try {
    const { productId } = req.params;
    const { name, price, description, inventory } = req.body;

    // Find the product to update
    const product = await Product.findByIdAndUpdate(productId, {
      name,
      price,
      description,
      isActive,
      inventory,
    }, { new: true });

    if (!product) {
      return res.status(404).json({ message: 'Product not found' });
    }

    res.json({ message: 'Product updated successfully', product });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: 'Error updating product' });
  }
};

// archive product controller
exports.archiveProduct = async (req, res) => {
  try {
    const { productId } = req.params;

    // Find the product to archive
    const product = await Product.findById(productId);

    if (!product) {
      return res.status(404).json({ message: 'Product not found' });
    }else if (product.isActive === false){
      return res.status(404).json({ message: 'Product already archived' });
    }

    product.isActive = false;

    await product.save();

    res.json({ message: 'Product archived successfully' });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: 'Error archiving product' });
  }
};


// activate product controller
exports.activateProduct = async (req, res) => {
  try {
    const { productId } = req.params;

    // Find the product to archive
    const product = await Product.findById(productId);

    if (!product) {
      return res.status(404).json({ message: 'Product not found' });
    }else if (product.isActive === true){
      return res.status(404).json({ message: 'Product already active' });
    }

    product.isActive = true;

    await product.save();

    res.json({ message: 'Product activated successfully' });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: 'Error activating product' });
  }
};


// Controller to create an order || check-out
exports.createOrder = async (req, res, next) => {
  try {
    let cartItems = req.body.orderedItems;

    // Fetch product prices from the database
       await Product.find({ _id: { $in: cartItems.map(item => item.productId) } }).then( result => {
        for (i = 0 ; i < result.length; i++) {
          cartItems[i].price = result[i].price;
        }
       });

      // Create the order with retrieved prices
          const newOrder = new Order({
            userId: req.user.id,
            products: cartItems,
            totalAmount: calculateTotalPrice(cartItems)
          });

          // Save the order and update inventory
          await newOrder.save();
            await updateProductInventory(cartItems);


          // Update User orders
          await User.findById(req.user.id).then( result => {

            const newOrderUserUpdate = {
              products: cartItems,
              totalAmount: calculateTotalPrice(cartItems),
              purchasedOn : new Date()
            }
            
            result.orders.push(newOrderUserUpdate);

            result.save();
          })



          res.status(201).json({ message: 'Order created successfully', newOrder });
        } catch (error) {
          console.error(error);
          res.status(500).json({ message: 'Error creating order' });
        }
      };


// Helper functions for calculating total price and updating inventory
function calculateTotalPrice(cartItems) {
    return cartItems.reduce((total, item) => {
    const itemPrice = Number(item.price); // Ensure price is a number
    const itemQuantity = Number(item.quantity); // Ensure quantity is a number
    return total + (itemPrice * itemQuantity);
  }, 0);
}

async function updateProductInventory(cartItems) {
  try {
    await Promise.all(
      cartItems.map(async item => {
        const product = await Product.findById(item.productId);

        if (!product) {
          throw new Error(`Product not found: ${item.productId}`);
        }

        // Ensure quantity doesn't go below zero
        const newQuantity = Math.max(0, product.inventory - item.quantity);

        product.inventory = newQuantity;
        await product.save();
      })
    );
  } catch (error) {
    console.error('Error updating product quantities:', error);
    // Handle the error appropriately (e.g., rollback order creation)
  }
}



// My Cart

exports.addProductToCart = async (req, res) => {
   try {
      const { productId, quantity } = req.body;

      // Find the user
      const user = await User.findById(req.user.id);

      // Check if the cart array exists
      if (!user.myCart) {
        user.myCart = [];
      }

      const existingItemIndex = user.myCart.findIndex(item => item.productId === productId);

      if (existingItemIndex !== -1) {
        // Update quantity of existing item
        user.myCart[existingItemIndex].quantity += quantity;
      } else {
        if (quantity <= 0) {
          return res.json({ message: 'Provide valid quantity' });
        }
        // Add new item to cart
        const product = await Product.findById(productId);
        user.myCart.push({
          productId,
          name: product.name,
          quantity
        });
      }

      await user.save(); // Save the updated user with cart items

      res.json({ message: 'Product added to cart successfully' });
    } catch (error) {
      console.error(error);
      res.status(500).json({ message: 'Error adding product to cart' });
    }
  };

exports.updateProductQuantity = async (req, res) => {
  try {
      const { productId, quantity } = req.body;

      // Find the user
      const user = await User.findById(req.user.id);

      if (!user.myCart) {
        return res.status(400).json({ message: 'Cart is empty' });
      }

      const itemIndex = user.myCart.findIndex(item => item.productId === productId);

      if (itemIndex === -1) {
        return res.status(404).json({ message: 'Product not found in cart' });
      }

      // Validate quantity (e.g., must be positive, not exceed available inventory)
      if (quantity <= 0) {
        return res.status(400).json({ message: 'Quantity must be greater than zero' });
      }

      // Update quantity in the cart
      user.myCart[itemIndex].quantity = quantity;

      await user.save(); // Save the updated cart

      res.json({ message: 'Product quantity updated successfully' });
      console.log(user.myCart);
    } catch (error) {
      console.error(error);
      res.status(500).json({ message: 'Error updating product quantity' });
    }
  };

exports.removeProductFromCart = async (req, res) => {
  try {
    const productId = req.params.productId;
    const user = await User.findById(req.user.id);
    const existingItemIndex = user.myCart.findIndex(item => item.productId === productId);

    let x = await User.findByIdAndUpdate(
      req.user.id,
      {
        $pull: { myCart: { productId } }
      },
      { new: true } // Return the updated user document
    ).exec();

    if (existingItemIndex <= 0) {
      res.json({ message: 'Product not in cart' });  
    }else{
    res.json({ message: 'Product removed from cart successfully' });
  }
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: 'Error removing product from cart' });
  }
};

exports.getCartDetails = async (req, res) => {
  try {
    const user = await User.findById(req.user.id);

    if (!user || !user.myCart || user.myCart.length < 0) {
      return res.json({ cartItems: [], totalPrice: 0 }); // Handle empty cart
    }

    const cartItems = user.myCart;
    let totalPrice = 0;

    for (const item of cartItems) {
      const findItemPrice = await Product.findById(item.productId);
      const subtotal = findItemPrice.price * item.quantity;
      totalPrice += subtotal;
      item.price = findItemPrice.price;

      // Add subtotal to the item object for clarity in response
      item.subtotal = subtotal;
    }

    res.json({ cartItems, totalPrice });
  } catch (error) {
    console.error(error);
    res.status(500).json({ message: 'Error fetching cart details' });
  }
};