const advancedResults = (Model, populate) => async (req, res, next) => {
  try {
    // Copy req.query
    const reqQuery = { ...req.query };
    
    // Fields to exclude
    const removeFields = ['select', 'sort', 'page', 'limit'];
    removeFields.forEach(param => delete reqQuery[param]);
    
    // Create query string
    let queryStr = JSON.stringify(reqQuery);
    
    // Create operators ($gt, $gte, etc)
    queryStr = queryStr.replace(/\b(gt|gte|lt|lte|in)\b/g, match => `$${match}`);
    
    // Parse the query conditions
    const queryConditions = JSON.parse(queryStr);
    
    // Initialize base query - handle both model classes and mongoose models
    let query;
    let modelInstance;
    
    // Get the model instance based on the type
    if (typeof Model === 'function' && typeof Model.find === 'function') {
      // It's a model class with static find method (like BaseModel)
      query = Model.find(queryConditions);
    } else if (typeof Model === 'function' && Model.model && typeof Model.model.find === 'function') {
      // It's a custom model class with a static model property
      query = Model.model.find(queryConditions);
    } else if (typeof Model.find === 'function') {
      // It's a direct mongoose model
      query = Model.find(queryConditions);
    } else {
      throw new Error('Invalid model provided to advancedResults. Model does not have a find method.');
    }
    
    // Handle select fields
    if (req.query.select) {
      const fields = req.query.select.split(',').join(' ');
      query = query.select(fields);
    }
    
    // Handle sorting
    let sortBy = '-createdAt';
    if (req.query.sort) {
      sortBy = req.query.sort.split(',').join(' ');
    }
    
    // Apply sorting
    if (sortBy) {
      query = query.sort(sortBy);
    }
    
    // Pagination
    const page = parseInt(req.query.page, 10) || 1;
    const limit = parseInt(req.query.limit, 10) || 25;
    const startIndex = (page - 1) * limit;
    const endIndex = page * limit;
    
    // Execute count query - handle different model types
    let total;
    if (typeof Model === 'function' && typeof Model.countDocuments === 'function') {
      total = await Model.countDocuments(queryConditions);
    } else if (typeof Model === 'function' && Model.model && typeof Model.model.countDocuments === 'function') {
      total = await Model.model.countDocuments(queryConditions);
    } else if (typeof Model.countDocuments === 'function') {
      total = await Model.countDocuments(queryConditions);
    } else {
      // Fallback to using find().count() if countDocuments is not available
      const results = await query.exec();
      total = results.length;
    }
    
    // Apply pagination
    if (query && typeof query.skip === 'function' && typeof query.limit === 'function') {
      query = query.skip(startIndex).limit(limit);
    }
    
    // Apply population if specified and query is valid
    if (populate && query && typeof query.populate === 'function') {
      if (Array.isArray(populate)) {
        populate.forEach(pop => {
          // Handle 'user' population by mapping it to 'userId'
          if (pop === 'user' || (typeof pop === 'object' && pop.path === 'user')) {
            query = query.populate({
              path: 'userId',
              select: 'name email phone',
              ...(typeof pop === 'object' ? pop : {})
            });
          } else {
            query = query.populate(pop);
          }
        });
      } else if (populate === 'user' || (typeof populate === 'object' && populate.path === 'user')) {
        // Handle single 'user' population
        query = query.populate({
          path: 'userId',
          select: 'name email phone',
          ...(typeof populate === 'object' ? populate : {})
        });
      } else {
        query = query.populate(populate);
      }
    }
    
    // Execute the final query
    const results = query && typeof query.exec === 'function' 
      ? await query.exec() 
      : [];
    
    // Build pagination result
    const pagination = {};
    
    if (endIndex < total) {
      pagination.next = {
        page: page + 1,
        limit
      };
    }
    
    if (startIndex > 0) {
      pagination.prev = {
        page: page - 1,
        limit
      };
    }
    
    res.advancedResults = {
      success: true,
      count: results.length,
      pagination,
      total,
      data: results
    };
    
    next();
  } catch (err) {
    console.error('Error in advancedResults middleware:', err);
    res.status(500).json({
      success: false,
      error: 'Server Error',
      message: err.message
    });
  }
};

module.exports = advancedResults;
