const CashCollection = require('../models/cashCollection');
const DeliveryBoy = require('../models/DeliveryBoy');
const asyncHandler = require('../middleware/async');
const ErrorResponse = require('../utils/errorResponse');
const mongoose = require('mongoose');

// @desc    Get all cash collections
// @route   GET /api/v1/cash-collections
// @access  Private/Admin
const getCashCollections = asyncHandler(async (req, res, next) => {
  const { search, deliveryBoy, status, startDate, endDate } = req.query;
  
  let query = {};
  
  if (search) {
    console.log('Searching for delivery boys with term:', search);
    const deliveryBoys = await DeliveryBoy.find({ 
      name: { $regex: search, $options: 'i' } 
    }).select('_id name');
    
    console.log('Found delivery boys:', deliveryBoys);
    const deliveryBoyIds = deliveryBoys.map(db => db._id);
    console.log('Using delivery boy IDs for search:', deliveryBoyIds);

    query.$or = [
      { orderId: { $regex: search, $options: 'i' } },
      { deliveryBoy: { $in: deliveryBoyIds } }
    ];
  }
  
  if (deliveryBoy) {
    query.deliveryBoy = deliveryBoy;
  }
  
  if (status) {
    query.status = status;
  }
  
  // Date range filter
  if (startDate || endDate) {
    query.collectionDate = {};
    if (startDate) query.collectionDate.$gte = new Date(startDate);
    if (endDate) {
      const endOfDay = new Date(endDate);
      endOfDay.setHours(23, 59, 59, 999);
      query.collectionDate.$lte = endOfDay;
    }
  }
  
  console.log('Final query for cash collections:', JSON.stringify(query, null, 2));
  
  const cashCollections = await CashCollection.find(query)
    .populate('deliveryBoy', 'name phone')
    .populate('collectedBy', 'name')
    .sort('-collectionDate');
    
  console.log('Found cash collections:', cashCollections.length);
  if (cashCollections.length > 0) {
    console.log('Sample cash collection with delivery boy:', {
      _id: cashCollections[0]._id,
      deliveryBoy: cashCollections[0].deliveryBoy,
      deliveryBoyId: cashCollections[0].deliveryBoy?._id,
      hasDeliveryBoy: !!cashCollections[0].deliveryBoy
    });
  }
  
  res.status(200).json({
    success: true,
    count: cashCollections.length,
    data: cashCollections,
  });
});

// @desc    Get single cash collection
// @route   GET /api/v1/cash-collections/:id
// @access  Private/Admin
const getCashCollection = asyncHandler(async (req, res, next) => {
  const cashCollection = await CashCollection.findById(req.params.id)
    .populate('deliveryBoy', 'name phone')
    .populate('collectedBy', 'name');
  
  if (!cashCollection) {
    return next(
      new ErrorResponse(`Cash collection not found with id of ${req.params.id}`, 404)
    );
  }
  
  res.status(200).json({
    success: true,
    data: cashCollection,
  });
});

// @desc    Create new cash collection
// @route   POST /api/v1/cash-collections
// @access  Private/Admin
const createCashCollection = asyncHandler(async (req, res, next) => {
  // Add user to req.body
  req.body.collectedBy = req.user.id;

  // Validate deliveryBoy ID
  if (req.body.deliveryBoy && !mongoose.Types.ObjectId.isValid(req.body.deliveryBoy)) {
    return next(new ErrorResponse('Invalid Delivery Boy ID', 400));
  }
  
  // Set handover date if status is handed_over
  if (req.body.status === 'handed_over') {
    req.body.handoverDate = Date.now();
  }
  
  const cashCollection = await CashCollection.create(req.body);

  // Populate deliveryBoy field after saving
  const populatedCollection = await CashCollection.findById(cashCollection._id)
    .populate('deliveryBoy', 'name phone');
  
  res.status(201).json({
    success: true,
    data: populatedCollection,
  });
});

// @desc    Update cash collection
// @route   PUT /api/v1/cash-collections/:id
// @access  Private/Admin
const updateCashCollection = asyncHandler(async (req, res, next) => {
  let cashCollection = await CashCollection.findById(req.params.id);
  
  if (!cashCollection) {
    return next(
      new ErrorResponse(`Cash collection not found with id of ${req.params.id}`, 404)
    );
  }
  
  // Update fields that are allowed to be updated
  const { status, notes, amount, collectionDate, deliveryBoy } = req.body;
  if (status) {
    cashCollection.status = status;
    if (status === 'handed_over' && !cashCollection.handoverDate) {
      cashCollection.handoverDate = Date.now();
    }
  }
  if (notes) cashCollection.notes = notes;
  if (amount) cashCollection.amount = amount;
  if (collectionDate) cashCollection.collectionDate = collectionDate;
  if (deliveryBoy) cashCollection.deliveryBoy = deliveryBoy;
  
  await cashCollection.save();
  
  res.status(200).json({
    success: true,
    data: cashCollection,
  });
});

// @desc    Delete cash collection
// @route   DELETE /api/v1/cash-collections/:id
// @access  Private/Admin
const deleteCashCollection = asyncHandler(async (req, res, next) => {
  const cashCollection = await CashCollection.findByIdAndDelete(req.params.id);
  
  if (!cashCollection) {
    return next(
      new ErrorResponse(`Cash collection not found with id of ${req.params.id}`, 404)
    );
  }
  
  res.status(200).json({
    success: true,
    data: {},
  });
});

module.exports = {
  getCashCollections,
  getCashCollection,
  createCashCollection,
  updateCashCollection,
  deleteCashCollection,
};
