import StockTransaction from '../models/StockTransaction.js';
import Product from '../models/Product.js';

const applyStockChange = async (productId, transactionType, quantityMoved) => {
  const product = await Product.findById(productId);
  if (!product) {
    throw new Error('Product not found');
  }

  if (transactionType === 'Stock In') {
    product.quantityInStock += quantityMoved;
  } else {
    if (product.quantityInStock < quantityMoved) {
      throw new Error('Insufficient stock for this transaction');
    }
    product.quantityInStock -= quantityMoved;
  }

  await product.save();
  return product;
};

const revertStockChange = async (productId, transactionType, quantityMoved) => {
  const product = await Product.findById(productId);
  if (!product) {
    throw new Error('Product not found');
  }

  if (transactionType === 'Stock In') {
    if (product.quantityInStock < quantityMoved) {
      throw new Error('Cannot revert transaction: stock would become negative');
    }
    product.quantityInStock -= quantityMoved;
  } else {
    product.quantityInStock += quantityMoved;
  }

  await product.save();
};

export const createStockTransaction = async (req, res) => {
  try {
    const { productId, warehouseId, transactionDate, quantityMoved, transactionType } = req.body;

    await applyStockChange(productId, transactionType, quantityMoved);

    const transaction = new StockTransaction({
      productId,
      warehouseId,
      transactionDate,
      quantityMoved,
      transactionType,
    });

    await transaction.save();
    const populated = await transaction.populate('productId warehouseId');
    res.status(201).json({ message: 'Transaction created successfully', transaction: populated });
  } catch (error) {
    res.status(500).json({ message: error.message });
  }
};

export const getAllStockTransactions = async (req, res) => {
  try {
    const transactions = await StockTransaction.find()
      .populate('productId warehouseId')
      .sort({ transactionDate: -1 });
    res.status(200).json(transactions);
  } catch (error) {
    res.status(500).json({ message: error.message });
  }
};

export const getStockTransactionById = async (req, res) => {
  try {
    const transaction = await StockTransaction.findById(req.params.id).populate('productId warehouseId');
    if (!transaction) {
      return res.status(404).json({ message: 'Transaction not found' });
    }
    res.status(200).json(transaction);
  } catch (error) {
    res.status(500).json({ message: error.message });
  }
};

export const updateStockTransaction = async (req, res) => {
  try {
    const { productId, warehouseId, transactionDate, quantityMoved, transactionType } = req.body;

    const transaction = await StockTransaction.findById(req.params.id);
    if (!transaction) {
      return res.status(404).json({ message: 'Transaction not found' });
    }

    await revertStockChange(
      transaction.productId,
      transaction.transactionType,
      transaction.quantityMoved
    );

    const newProductId = productId || transaction.productId;
    const newType = transactionType || transaction.transactionType;
    const newQuantity = quantityMoved || transaction.quantityMoved;

    await applyStockChange(newProductId, newType, newQuantity);

    transaction.productId = newProductId;
    transaction.warehouseId = warehouseId || transaction.warehouseId;
    transaction.transactionDate = transactionDate || transaction.transactionDate;
    transaction.quantityMoved = newQuantity;
    transaction.transactionType = newType;

    await transaction.save();
    const updated = await StockTransaction.findById(req.params.id).populate('productId warehouseId');
    res.status(200).json({ message: 'Transaction updated successfully', transaction: updated });
  } catch (error) {
    res.status(500).json({ message: error.message });
  }
};

export const deleteStockTransaction = async (req, res) => {
  try {
    const transaction = await StockTransaction.findById(req.params.id);
    if (!transaction) {
      return res.status(404).json({ message: 'Transaction not found' });
    }

    await revertStockChange(
      transaction.productId,
      transaction.transactionType,
      transaction.quantityMoved
    );

    await StockTransaction.findByIdAndDelete(req.params.id);
    res.status(200).json({ message: 'Transaction deleted successfully' });
  } catch (error) {
    res.status(500).json({ message: error.message });
  }
};

export const getStockReport = async (req, res) => {
  try {
    const { startDate, endDate, reportType } = req.query;

    let dateQuery = {};
    if (startDate && endDate) {
      const start = new Date(startDate);
      start.setHours(0, 0, 0, 0);
      const end = new Date(endDate);
      end.setHours(23, 59, 59, 999);
      dateQuery = { transactionDate: { $gte: start, $lte: end } };
    }

    const products = await Product.find().sort({ productName: 1 });
    const transactions = await StockTransaction.find(dateQuery).populate('productId warehouseId');

    const stockIn = transactions.filter((t) => t.transactionType === 'Stock In');
    const stockOut = transactions.filter((t) => t.transactionType === 'Stock Out');

    const totalStockIn = stockIn.reduce((sum, t) => sum + t.quantityMoved, 0);
    const totalStockOut = stockOut.reduce((sum, t) => sum + t.quantityMoved, 0);
    const totalAvailableStock = products.reduce((sum, p) => sum + p.quantityInStock, 0);

    res.status(200).json({
      message: `${reportType || 'Stock'} Report`,
      reportType: reportType || 'custom',
      period: { startDate, endDate },
      summary: {
        totalAvailableStock,
        totalStockIn,
        totalStockOut,
        transactionCount: transactions.length,
      },
      availableStock: products,
      stockInTransactions: stockIn,
      stockOutTransactions: stockOut,
    });
  } catch (error) {
    res.status(500).json({ message: error.message });
  }
};
