const FundsTransfer = require('../models/fundsTransfer');
const DeliveryBoy = require('../models/DeliveryBoy');
const { validationResult } = require('express-validator');
const mongoose = require('mongoose');
const asyncHandler = require('../middleware/async');
const ErrorResponse = require('../utils/errorResponse');

// @desc    Get all funds transfers
// @route   GET /api/v1/funds-transfers
// @access  Private/Admin
const getFundsTransfers = 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 = [
      { transactionId: { $regex: search, $options: 'i' } },
      { deliveryBoy: { $in: deliveryBoyIds } }
    ];
  }
  
  if (deliveryBoy) {
    query.deliveryBoy = deliveryBoy;
  }
  
  if (status) {
    query.status = status;
  }
  
  // Date range filter
  if (startDate || endDate) {
    query.date = {};
    if (startDate) query.date.$gte = new Date(startDate);
    if (endDate) {
      const endOfDay = new Date(endDate);
      endOfDay.setHours(23, 59, 59, 999);
      query.date.$lte = endOfDay;
    }
  }
  
  console.log('Final query for funds transfers:', JSON.stringify(query, null, 2));
  
  const fundsTransfers = await FundsTransfer.find(query)
    .populate('deliveryBoy', 'name phone')
    .populate('createdBy', 'name')
    .sort('-createdAt');
    
  console.log('Found funds transfers:', fundsTransfers.length);
  if (fundsTransfers.length > 0) {
    console.log('Sample funds transfer with delivery boy:', {
      _id: fundsTransfers[0]._id,
      deliveryBoy: fundsTransfers[0].deliveryBoy,
      deliveryBoyId: fundsTransfers[0].deliveryBoy?._id
    });
  }
  
  res.status(200).json({
    success: true,
    count: fundsTransfers.length,
    data: fundsTransfers,
  });
});

// @desc    Get single funds transfer
// @route   GET /api/v1/funds-transfers/:id
// @access  Private/Admin
const getFundsTransfer = asyncHandler(async (req, res, next) => {
  const fundsTransfer = await FundsTransfer.findById(req.params.id)
    .populate('deliveryBoy', 'name phone')
    .populate('createdBy', 'name');
  
  if (!fundsTransfer) {
    return next(
      new ErrorResponse(`Funds transfer not found with id of ${req.params.id}`, 404)
    );
  }
  
  res.status(200).json({
    success: true,
    data: fundsTransfer,
  });
});

// @desc    Create new funds transfer
// @route   POST /api/v1/funds-transfers
// @access  Private/Admin
const createFundsTransfer = asyncHandler(async (req, res, next) => {
  // Add user to req.body
  req.body.createdBy = 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));
  }

  console.log('Creating funds transfer with delivery boy ID:', req.body.deliveryBoy);

  // Create new instance and save to ensure pre-save hooks are triggered
  const fundsTransfer = new FundsTransfer(req.body);
  await fundsTransfer.save();
  
  // Populate deliveryBoy field after saving
  const populatedTransfer = await FundsTransfer.findById(fundsTransfer._id)
    .populate('deliveryBoy', 'name phone');

  res.status(201).json({
    success: true,
    data: populatedTransfer,
  });
});

// @desc    Update funds transfer
// @route   PUT /api/v1/funds-transfers/:id
// @access  Private/Admin
const updateFundsTransfer = asyncHandler(async (req, res, next) => {
  let fundsTransfer = await FundsTransfer.findById(req.params.id);
  
  if (!fundsTransfer) {
    return next(
      new ErrorResponse(`Funds transfer not found with id of ${req.params.id}`, 404)
    );
  }
  
  // Update fields that are allowed to be updated
  const { status, notes, amount, method, deliveryBoy } = req.body;
  if (status) fundsTransfer.status = status;
  if (notes) fundsTransfer.notes = notes;
  if (amount) fundsTransfer.amount = amount;
  if (method) fundsTransfer.method = method;
  if (deliveryBoy) fundsTransfer.deliveryBoy = deliveryBoy;
  
  await fundsTransfer.save();
  
  res.status(200).json({
    success: true,
    data: fundsTransfer,
  });
});

// @desc    Delete funds transfer
// @route   DELETE /api/v1/funds-transfers/:id
// @access  Private/Admin
const deleteFundsTransfer = asyncHandler(async (req, res, next) => {
  const fundsTransfer = await FundsTransfer.findByIdAndDelete(req.params.id);
  
  if (!fundsTransfer) {
    return next(
      new ErrorResponse(`Funds transfer not found with id of ${req.params.id}`, 404)
    );
  }
  
  res.status(200).json({
    success: true,
    data: {},
  });
});

module.exports = {
  getFundsTransfers,
  getFundsTransfer,
  createFundsTransfer,
  updateFundsTransfer,
  deleteFundsTransfer,
};
