const Item = require('../models/Item');




const BranchInventory = require('../models/BranchInventory'); // Make sure to import the BranchInventory model
const Branch = require('../models/Branch'); // Import Branch model
const { request } = require('https');

// Update an item
const mongoose = require('mongoose');


async function fixDuplicateCodes() {
  try {
    // Step 1: Find duplicates by grouping code and companyId
    const duplicates = await Item.aggregate([
      {
        $group: {
          _id: { code: "$code", companyId: "$companyId" },
          count: { $sum: 1 },
          docs: { $push: "$_id" } // Push all duplicate IDs into an array
        }
      },
      { $match: { count: { $gt: 1 } } } // Only groups with duplicates
    ]);

    // Step 2: Update duplicates with random 4-digit codes
    for (const duplicate of duplicates) {
      const [keepOne, ...toUpdate] = duplicate.docs; // Keep the first one, update the rest
      
      for (const id of toUpdate) {
        const randomCode = Math.floor(1000 + Math.random() * 9000).toString(); // Generate random 4-digit code
        await Item.updateOne(
          { _id: id },
          { $set: { code: randomCode } }
        );
        console.log(`Updated document ${id} with new code: ${randomCode}`);
      }
    }

    console.log("Duplicate codes fixed successfully.");
  } catch (error) {
    console.error("Error fixing duplicates:", error.message);
  } finally {
    mongoose.connection.close();
  }
}


















// Controller function to bulk import items
exports.bulkImportItems = async (req, res) => {
  try {


//    fixDuplicateCodes();

//return;

  //  Get items array from request body
   await Item.collection.createIndex({ code: 1, companyId: 1 }, { unique: true });
    console.log('Index created successfully');
  const updateQuantity=req.body.updateQuantity;


  console.log("Update Quantity:", updateQuantity); // true if checked, false otherwise
 

  if( updateQuantity) //if update or insert is true
   { 
    
    await updateItems(req.body);
   
   return( res.status(200).json({success:true, message: 'Items imported successfully!' }));
   }


    const items = req.body.items;
    const companyId=req.body.companyId; // assume all items have same company code
    const branchId=req.body.branchId
  



    // Validate if items array exists and has data
    if (!items || !Array.isArray(items) || items.length === 0) {
      return res.status(400).json({ message: 'No items provided for import.' });
    }
 
    // Prepare items data for insertion
    const itemsToInsert = items.map(item => ({
      name: item.name,
      code: item.code,
      avg_price:  Number(item.avg_price.replace(/,/g, '')),
      selling_price:Number(item.selling_price.replace(/,/g, '')),
      quantity:  Number(item.quantity.replace(/,/g, '')),
      type:item.type||'shop',
      companyId,
      status: item.status || 'active',
      image_url: item.image_url || ''
    }));

 

     // Step 1: Save all items to the database
     const savedItems = await Item.insertMany(itemsToInsert);

// Step 2: Fetch all branches for the company
const branches = await Branch.find({ companyId });

// Check if any branches were found
if (branches.length === 0) {
  // Send message to frontend
   await Item.deleteMany({ companyId});
  console.log('Deleted items with companyId:', companyId);
  return res.status(404).json({ message: "No branches found for this company" });
}

 // Step 3: Initialize inventory for each branch and item
 const inventoryPromises = [];
 savedItems.forEach(savedItem => {
  branches.forEach(branch => {
    // Determine the quantity based on the branch match
    const quantity = (branch._id.toString() === branchId.toString()) ? savedItem.quantity : 0;
  //  const quantity =savedItem.quantity; //
    
    // Create the inventory record for each branch
    inventoryPromises.push(
      BranchInventory.create({
        companyId: companyId,
        branchId: branch._id,
        itemId: savedItem._id,
        quantity: quantity // Assign the imported quanity to current branch.
      })
    );
  });
});


 // Wait for all inventory initializations to complete
 await Promise.all(inventoryPromises);

 res.status(200).json({success:true, message: 'Items imported successfully!', data: savedItems  });


    } catch (error) {

// if there is error in importing clear all data because only some data is imported.
    // await Item.deleteMany({ companyId});
    // console.log('Deleted items with companyId:', companyId);
    // await BranchInventory.deleteMany({ companyId: objectId });
    // console.log('Deleted branch inventories with companyId:', companyId);

    console.error('Error during bulk item import :', error.message);
    res.status(500).json({ message: 'Network or other Error during bulk import', error });
  }
};










////////////////////////// only to update/import branch quantity
async function updateItems(data)
{

const items = data.items;
const companyId = data.companyId; // Assume all items have the same companyId
const branchId =data.branchId;

// Validate input
if (!items || !Array.isArray(items) || items.length === 0) {
  return  'No items provided for import.' ;
}

try {
  // Step 1: Insert or find items in the Item collection
  for (const item of items) {
    const quantityToAdd = Number(item.quantity.replace(/,/g, ''));

    // Insert or update the Item collection
    const savedItem = await Item.findOneAndUpdate(
      { code: item.code, companyId: companyId }, // Search criteria
      {
        $setOnInsert: {
          name: item.name,
          avg_price: Number(item.avg_price.replace(/,/g, '')),
          selling_price: Number(item.selling_price.replace(/,/g, '')),
          type: item.type || 'shop',
          status: item.status || 'active',
          image_url: item.image_url || '',
          companyId,
        }
      },
      { upsert: true, new: true, setDefaultsOnInsert: true }
    );

    // Step 2: Update quantity in BranchInventory
    await BranchInventory.findOneAndUpdate(
      {
        companyId: companyId,
        branchId: branchId,
        itemId: savedItem._id,
        
      },
      {
        $set: { quantity: quantityToAdd }, // Increment the quantity
      },
      { upsert: true, new: true } // Create new if it doesn't exist
    );
  }

  //return res.status(200).json({ message: 'Items imported and inventory updated successfully.' });
} catch (error) {
  console.error('Erro in updating items and inventory:', error);
 // return res.status(500).json({ message: 'Failed to process items.', error });
}
}

///////////////////////////////////


























exports.bulkImportItems2 = async (req, res) => {
  try {
    // Get items array from request body

  
    const items = req.body.items;
    const companyId=req.body.companyId; // assume all items have same company code
    const branchId=req.body.branchId
  
    // Validate if items array exists and has data
    if (!items || !Array.isArray(items) || items.length === 0) {
      return res.status(400).json({ message: 'No items provided for import.' });
    }

    
 
    const bulkOperations = items.map(item => ({
      updateOne: {
        filter: { companyId, code: item.code }, // Match each item by its code
        update: {
          $set: {
            name: item.name,
            avg_price: Number(item.avg_price.replace(/,/g, '')),
            selling_price: Number(item.selling_price.replace(/,/g, '')),
          //  quantity: Number(item.quantity.replace(/,/g, '')),
            companyId,
            status: item.status || 'active',
            image_url: item.image_url || ''
          }
        },
        upsert: true // Insert if not found
      }
    }));
    
    // Execute bulkWrite to update or insert each item based on code
    const result = await Item.bulkWrite(bulkOperations);
    



// Step 2: Fetch all branches for the company
const branches = await Branch.find({ companyId });

// Check if any branches were found
if (branches.length === 0) {
  // Send message to frontend
   await Item.deleteMany({ companyId});
  console.log('Deleted items with companyId:', companyId);
  return res.status(404).json({ message: "No branches found for this company" });
}




// Step 3: Initialize or update inventory for each branch and item
const inventoryOperations = [];
savedItems.forEach(savedItem => { // where is saved item defined??
  branches.forEach(branch => {
    // Determine the quantity based on the branch match
    const quantity = (branch._id.toString() === branchId.toString()) ? savedItem.quantity : 0;
    
    // Prepare the bulk operation for each branch's inventory
    inventoryOperations.push({
      updateOne: {
        filter: { companyId: companyId, branchId: branch._id, itemId: savedItem._id }, // Match by companyId, branchId, and itemId
        update: {
          $set: {
            quantity: quantity // Set quantity based on the branch match
          }
        },
        upsert: true // Insert if not found
      }
    });
  });
});

// Execute the bulk write operation
const result2 = await BranchInventory.bulkWrite(inventoryOperations);







    res.status(200).json({success:true, message: 'Items imported successfully!', data: savedItems  });
  } catch (error) {

// if there is error in importing clear all data because only some data is imported.
    // await Item.deleteMany({ companyId});
    // console.log('Deleted items with companyId:', companyId);
    // await BranchInventory.deleteMany({ companyId: objectId });
    // console.log('Deleted branch inventories with companyId:', companyId);

    console.error('Error during bulk import:', error.message);
    res.status(500).json({ message: 'Network or other Error during bulk import', error });
  }
};











// Create a new item for a specific company
exports.createItem = async (req, res) => {
  try {


   
  
  const { name, code, avg_price, selling_price, companyId ,type,attachmentRequired,kitchen,category,stockRequired} = req.body;
    const image_url = req.file ? `/uploads/${req.file.filename}` : null;

    const expDate = req.body.expDate || null; // Accept a single date or null

// Validate and transform the date
const expDates = expDate
  ? [{ expDate: new Date(expDate) }] // Wrap valid date in an object
  : []; // Use an empty array if no date is provided



   // Step 1: Create the new item
 const newItem = new Item({
  name,
  code,
  avg_price,
  selling_price,
  type,
  kitchenId:kitchen,
  categoryId: category,
  status: 'active',
  attachmentReq:attachmentRequired=='yes' ? true : false,
  needStock:stockRequired=='yes' ? true : false,
  companyId,  
  image_url
});

    const savedItem = await newItem.save();

    // Step 2: Fetch all branches for the company
    const branches = await Branch.find({ companyId });

    // Step 3: Initialize inventory for each branch
    const inventoryPromises = branches.map(branch => {
      return BranchInventory.create({
        companyId: companyId,
        branchId: branch._id,
        itemId: savedItem._id,
        quantity: 0 // Initial quantity set to 0
      });
    });
   
    await Promise.all(inventoryPromises);
   

    res.status(201).json({ item: savedItem, message: 'Item and branch inventories initialized successfully' });
  } catch (error) {
    console.error('Error creating item and initializing inventory:', error);
    res.status(500).json({ message: 'Error creating item', error: error.message });
  }
};





// Get all items for a specific company
exports.getItems = async (req, res) => {
  try {
    const { companyId } = req.query;
    const items = await Item.find({ company: companyId });
    res.status(200).json(items); // Send the items back as JSON
  } catch (error) {
    res.status(500).json({ message: 'Server error', error: error.message });
  }
};


// Fetch all items
exports.getAllItems = async (req, res) => {
    try {
      const companyId=req.query.companyId;
      const branchId=req.query.branchIdId;

   
      const status=req.query.status?req.query.status:"active";
        const items = await Item.find({companyId:companyId}).sort({code:1}); // Retrieve all items from the database
      if (!items) {
        return res.status(404).json({ message: 'No items found' });
      }


    
      res.status(200).json(items); // Send the items back as JSON


    } catch (error) {
      console.error('Error fetching items:', error);
      res.status(500).json({ message: 'Server error' }); // Ensure server always responds with JSON
    }
  };
  





exports.updateItem = async (req, res) => {
  try {
    const { itemId } = req.params;
    const { 
      name, 
      code, 
      avg_price, 
      selling_price, 
      type, 
      kitchen, 
      category, 
      attachmentRequired ,
      stockRequired,
      expDate
    } = req.body;

    const image_url = req.file ? `/uploads/${req.file.filename}` : null;

    // Parse `kitchenId` and `categoryId` as MongoDB ObjectIds
    // const kitchenObjectId = kitchen ? new mongoose.Types.ObjectId(kitchen) : undefined;
    // const categoryObjectId = category ? new mongoose.Types.ObjectId(category) : undefined;

    // Build the fields to update
    const fields = {
      name, 
      code, 
      avg_price, 
      selling_price, 
      type, 
      kitchenId: kitchen,
      categoryId: category,
      attachmentReq: attachmentRequired === 'yes',
      needStock:stockRequired==='yes' ,
    };
    if (image_url) {
      fields.image_url = image_url;
    }

    // Update the item in the database
    const updatedItem = await Item.findByIdAndUpdate(itemId, fields, { new: true });
console.log(req.body);
console.log(updatedItem);


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

    res.status(200).json(updatedItem);

  } catch (error) {
    res.status(500).json({ message: 'Error updating item', error: error.message });
  }
};


// Delete an item
exports.deleteItem = async (req, res) => {
  try {
    const { itemId } = req.params;
    await Item.findByIdAndDelete(itemId);
    res.json({ message: 'Item deleted successfully' });
  } catch (error) {
    res.status(500).json({ message: 'Error deleting item', error: error.message });
  }
};
