


const express = require('express');
const router = express.Router();

// Import necessary models
const BranchInventory = require('../models/BranchInventory');
const Transfer = require('../models/Transfer');

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








exports.processTransferHandler=async(req, res)=> {

  
  const { transferId } = req.params;
  const { status, reason } = req.query; // Expect `status` and optional `reason` from the front end

  try {
    const result = await processTransfer(transferId, status, reason); // Call the main processing function
    res.status(200).json(result); // Send the result back to the front end
  } catch (error) {
    res.status(500).json({ error: error.message }); // Send error message if something goes wrong
  }
}




async function processTransfer(transferId,status, reason) {



  const transfer = await Transfer.findById(transferId);
  if (!transfer || transfer.status !== 'Pending') {
    throw new Error('Transfer not found or already processed');
  }
  
  transfer.status = status;
  transfer.updatedAt = Date.now(); // Automatically updated by middleware
  if (status === 'Rejected') {
    transfer.reasonForRejection = reason;



  // Find or create the inventory in `fromBranch` and add back quantity
  let fromInventory = await BranchInventory.findOne({ branchId: transfer.fromBranchId, itemId: transfer.itemId });
  if (fromInventory) {
    fromInventory.quantity += transfer.quantity; // Increase quantity back to original amount
    
  } else {
    // Create inventory entry if it doesn't exist in `fromBranch`

   // console.log("current inv", fromInventory); 
    fromInventory = await BranchInventory.create({
      companyId: transfer.companyId,
      branchId: transfer.fromBranchId,
      itemId: transfer.itemId,
      quantity: transfer.quantity,
    });
  }
  await fromInventory.save();
  transfer.fromBranchBalance = fromInventory.quantity; // Update the balance after addition

  await transfer.save(); // Save the rejection status and inventory update
  return { message: 'Transfer rejected and items returned to fromBranch', transfer };
}

if (status === 'Returned') {
  transfer.reasonForRejection = reason;

  // Find or create the inventory in `fromBranch` and add back quantity
  let fromInventory = await BranchInventory.findOne({ branchId: transfer.fromBranchId, itemId: transfer.itemId });
  if (fromInventory) {
    fromInventory.quantity += transfer.quantity; // Increase quantity back to original amount
  } else {
    // Create inventory entry if it doesn't exist in `fromBranch`
    console.log("current inv", fromInventory); 
    fromInventory = await BranchInventory.create({
      companyId: transfer.companyId,
      branchId: transfer.fromBranchId,
      itemId: transfer.itemId,
      quantity: transfer.quantity,
    });
  }
  await fromInventory.save();
  transfer.fromBranchBalance = fromInventory.quantity; // Update the balance after addition

  await transfer.save(); // Save the returned status and inventory update
  return { message: 'Transfer returned and items added back to fromBranch', transfer };
}

  

  // Adjust branch balances here if accepted
  if (status === 'Accepted') {
    // Increase toBranch inventory and update toBranchBalance
    

   // . Increase quantity in `toBranch`
   let toInventory = await BranchInventory.findOne({ branchId: transfer.toBranchId, itemId: transfer.itemId });
   if (toInventory) {
     toInventory.quantity += transfer.quantity;
   } else {
     // Create inventory entry if it doesn't exist in `toBranch`
     toInventory = await BranchInventory.create({
      companyId: transfer.companyId,
       branchId: transfer.toBranchId,
       itemId: transfer.itemId,
       quantity: transfer.quantity,
     });
   }
   await toInventory.save();
   transfer.toBranchBalance = toInventory.quantity; // Update the balance after addition
 }
 

  await transfer.save();
  return transfer;
}







// Helper function to validate all items before performing a transfer
async function validateItemsBeforeTransfer(items, fromBranchId) {
  for (const item of items) {
    const { itemId, quantity } = item;

    // Check if the item exists in the fromBranch inventory
    const fromBranchInventory = await BranchInventory.findOne({ branchId: fromBranchId, itemId });
    if (!fromBranchInventory || fromBranchInventory.quantity < quantity) {
      throw new Error(`Insufficient stock in the source branch for item: ${item.name}`);
    }
  }
}


// Controller: Perform a transfer between branches
exports.performTransfer = async (req, res) => {
  try {
    const { companyId, fromBranchId, toBranchId, items } = req.body.transferCart;

    // Validate fromBranchId and toBranchId
    if (!fromBranchId || !toBranchId) {
      return res.status(400).json({ message: 'Source and destination branches must be specified.' });
    }

    // Step 1: Validate all items before performing the transferh
    await validateItemsBeforeTransfer(items, fromBranchId);

    // Step 2: Loop through each item to process the transfer
    for (const item of items) {
      const { itemId, quantity } = item;

      // Deduct quantity from fromBranch
      const fromBranchInventory = await BranchInventory.findOne({ branchId: fromBranchId, itemId });
      fromBranchInventory.quantity -= quantity;
      await fromBranchInventory.save();
// Get current balance of fromBranch
    const fromBranchBalance = fromBranchInventory.quantity;
      // Add quantity to toBranch

      // let toBranchInventory = await BranchInventory.findOne({ branchId: toBranchId, itemId });
      // if (toBranchInventory) {
      //   toBranchInventory.quantity += quantity;
      // } else {
      //   toBranchInventory = new BranchInventory({ companyId, branchId: toBranchId, itemId, quantity });
      // }
      // await toBranchInventory.save();
      // const toBranchBalance = toBranchInventory.quantity;
      

      const transfer = new Transfer({
        companyId,
        fromBranchId: fromBranchId,
        toBranchId: toBranchId,
        itemId,
        quantity,
        fromBranchBalance: fromBranchBalance, //  /* Current balance of fromBranch after deduction */,       after trasnfer performed without considering accepting and rejecting
        // toBranchBalance: toBranchBalance,  // it is better to update this at the time of accepting or rejecting
      
      });
    

      await transfer.save();
    }

    res.status(200).json({ success: true, message: 'Transfer successful!' });
  } catch (error) {
    console.error('Error during transfer:', error.message);
    res.status(400).json({ message: error.message });
  }
};





// Controller: Update a transfer
exports.updateTransfer = async (req, res) => { // update 
  try {
    const { transferId, fromBranchId, toBranchId, itemId, updatedQuantity } = req.body;

    // Find the transfer record
    const transfer = await Transfer.findById(transferId);
    if (!transfer) {
      return res.status(404).json({ message: 'Transfer not found' });
    }


// here there shall be status checking.....

    // Revert original quantity to the destination and source branches
    const originalQuantity = transfer.quantity;

    // Revert original quantity in the destination branch
    let toBranchInventory = await BranchInventory.findOne({ branchId: toBranchId, itemId });
    toBranchInventory.quantity -= originalQuantity;
    await toBranchInventory.save();

    // Add original quantity back to the source branch
    let fromBranchInventory = await BranchInventory.findOne({ branchId: fromBranchId, itemId });
    fromBranchInventory.quantity += originalQuantity;
    await fromBranchInventory.save();

    // Check if the updated quantity is available in the source branch
    if (fromBranchInventory.quantity < updatedQuantity) {
      return res.status(400).json({ message: 'Insufficient stock in the source branch to perform the update.' });
    }

    // Deduct updated quantity from source branch
    fromBranchInventory.quantity -= updatedQuantity;
    await fromBranchInventory.save();

    // Add updated quantity to destination branch
    toBranchInventory.quantity += updatedQuantity;
    await toBranchInventory.save();

    // Update balances in the transfer record
    transfer.quantity = updatedQuantity;
    transfer.fromBranchBalance = fromBranchInventory.quantity; // Update fromBranch balance
    transfer.toBranchBalance = toBranchInventory.quantity; // Update toBranch balance

    await transfer.save();

    res.status(200).json({ success: true, message: 'Transfer updated successfully!' });
  } catch (error) {
    console.error('Error updating transfer:', error);
    res.status(500).json({ message: 'Error updating transfer', error });
  }
};








// Controller: Update a transfer
exports.updateTransfer_org = async (req, res) => {
  try {
    const { transferId, fromBranchId, toBranchId, itemId, updatedQuantity } = req.body;

    // Find the transfer record
    const transfer = await Transfer.findById(transferId);
    if (!transfer) {
      return res.status(404).json({ message: 'Transfer not found' });
    }

    // Revert quantity in both branches to initial state before updating
    const originalQuantity = transfer.quantity;

    // Revert original quantity from the destination branch
    let toBranchInventory = await BranchInventory.findOne({ branchId: toBranchId, itemId });
    toBranchInventory.quantity -= originalQuantity;
    await toBranchInventory.save();

    // Add original quantity back to the source branch
    let fromBranchInventory = await BranchInventory.findOne({ branchId: fromBranchId, itemId });
    fromBranchInventory.quantity += originalQuantity;
    await fromBranchInventory.save();

    // Check if the updated quantity is available in the source branch
    if (fromBranchInventory.quantity < updatedQuantity) {
      return res.status(400).json({ message: 'Insufficient stock in the source branch to perform the update.' });
    }

    // Deduct updated quantity from source branch
    fromBranchInventory.quantity -= updatedQuantity;
    await fromBranchInventory.save();

    // Add updated quantity to destination branch
    toBranchInventory.quantity += updatedQuantity;
    await toBranchInventory.save();

    // Update transfer record
    transfer.quantity = updatedQuantity;
    await transfer.save();

    res.status(200).json({ success: true, message: 'Transfer updated successfully!' });
  } catch (error) {
    console.error('Error updating transfer:', error);
    res.status(500).json({ message: 'Error updating transfer', error });
  }
};






// Controller: Update a transfer
exports.updateTransfer = async (req, res) => {
  try {
    const { transferId, fromBranchId, toBranchId, itemId, updatedQuantity } = req.body;

    // Find the transfer record
    const transfer = await Transfer.findById(transferId);
    if (!transfer) {
      return res.status(404).json({ message: 'Transfer not found' });
    }

    // Revert quantity in both branches to initial state before updating
    const originalQuantity = transfer.quantity;

    // Revert original quantity from the destination branch
    let toBranchInventory = await BranchInventory.findOne({ branchId: toBranchId, itemId });
    toBranchInventory.quantity -= originalQuantity;
    await toBranchInventory.save();

    // Add original quantity back to the source branch
    let fromBranchInventory = await BranchInventory.findOne({ branchId: fromBranchId, itemId });
    fromBranchInventory.quantity += originalQuantity;
    await fromBranchInventory.save();

    // Check if the updated quantity is available in the source branch
    if (fromBranchInventory.quantity < updatedQuantity) {
      return res.status(400).json({ message: 'Insufficient stock in the source branch to perform the update.' });
    }

    // Deduct updated quantity from source branch
    fromBranchInventory.quantity -= updatedQuantity;
    await fromBranchInventory.save();

    // Add updated quantity to destination branch
    toBranchInventory.quantity += updatedQuantity;
    await toBranchInventory.save();

    // Update transfer record
    transfer.quantity = updatedQuantity;
    await transfer.save();

    res.status(200).json({ success: true, message: 'Transfer updated successfully!' });
  } catch (error) {
    console.error('Error updating transfer:', error);
    res.status(500).json({ message: 'Error updating transfer', error });
  }
};

// Controller: Delete a transfer
exports.deleteTransfer = async (req, res) => {
  try {
    const { transferId } = req.params;

    // Find the transfer record
    const transfer = await Transfer.findById(transferId);
    if (!transfer) {
      return res.status(404).json({ message: 'Transfer not found' });
    }

    const { fromBranch, toBranch, itemId, quantity } = transfer;

    // Revert quantity changes in both branches
    let toBranchInventory = await BranchInventory.findOne({ branchId: toBranch, itemId });
    toBranchInventory.quantity -= quantity;
    await toBranchInventory.save();

    let fromBranchInventory = await BranchInventory.findOne({ branchId: fromBranch, itemId });
    fromBranchInventory.quantity += quantity;
    await fromBranchInventory.save();

    // Delete the transfer record
    await transfer.delete();

    res.status(200).json({ success: true, message: 'Transfer deleted successfully!' });
  } catch (error) {
    console.error('Error deleting transfer:', error);
    res.status(500).json({ message: 'Error deleting transfer', error });
  }
};




// Controller: Get transfer report for a branch

exports.getTransferReport = async (req, res) => {
  try {
    const {companyId, branchId ,start,end} = req.query;

    const startDate = start
    ? new Date(start).setUTCHours(0, 0, 0, 0) // Set start date to beginning of the day
    : new Date().setUTCHours(0, 0, 0, 0); // Default to today at 00:00:00
  
  const endDate = end
    ? new Date(end).setUTCHours(23, 59, 59, 999) // Set end date to the end of the day
    : new Date().setUTCHours(23, 59, 59, 999); // Default to today at 23:59:59
  
  // Fetch transfers within the date range where the branch is either in 'fromBranch' or 'toBranch'
  const transfers = await Transfer.find({
    $or: [
      { fromBranchId: branchId },
      { toBranchId: branchId }
    ],
    createdAt: { $gte: new Date(startDate), $lte: new Date(endDate) } // Date range filter
  })
    .populate('fromBranchId toBranchId itemId', 'name')
    .sort({ createdAt: -1 })
    .lean();
  

    
    // Add an 'In/Out' type based on the current branch ID
    const formattedTransfers = transfers.map(transfer => {
     
      const transferType = transfer.fromBranchId._id.toString() === branchId ? 'Out' : 'In';
   
   
   
      return {
        ...transfer,
        transferType
      };
    });
    console.log("list of transfers are:",formattedTransfers)
    res.status(200).json(formattedTransfers);
  } catch (error) {
    console.error('Error fetching transfer report:', error);
    res.status(500).json({ message: 'Error fetching transfer report' });
  }
};





exports.getTransferReport_orggg = async (req, res) => {
  try {
    const { branchId } = req.query; // Get branchId from query parameters

    // Find all transfers where the branch is either in the "fromBranch" (out transfer) or "toBranch" (in transfer)
    const transfers = await Transfer.find({
      $or: [
        { fromBranch: branchId }, // Out transfers
        { toBranch: branchId }     // In transfers
      ]
    })
    .populate('fromBranch toBranch itemId', 'name') // Populate branch and item names
    .lean();

    // Process the transfers and categorize them
    const transferReport = transfers.map(transfer => {
      const isOutTransfer = String(transfer.fromBranch._id) === branchId;
      return {
        itemId: transfer.itemId._id,
        itemName: transfer.itemId.name,
        quantity: transfer.quantity,
        transferType: isOutTransfer ? 'Out Transfer' : 'In Transfer',
        fromBranch: transfer.fromBranch.name,
        toBranch: transfer.toBranch.name,
        createdAt: transfer.createdAt
      };
    });

    res.status(200).json(transferReport);
  } catch (error) {
    console.error('Error generating transfer report:', error);
    res.status(500).json({ message: 'Error generating transfer report', error: error.message });
  }
};
