text: const path = require("path");
  const asyncHandler = require("../middleware/async");
  const Bootcamp = require("../models/Bootcamp");
  const ErrorResponse = require("../utils/errorResponse");
  const geocoder = require("../utils/geocoder");
  
  // @desc    Get all bootcamps
  // @route   GET /api/v1/bootcamps
  // @access  Public
  exports.getBootcamps = asyncHandler(async (req, res, next) => {
  	res.status(200).json(res.advancedResults);
  });
  
  // @desc    Get single bootcamps
  // @route   GET /api/v1/bootcamps/:id
  // @access  Public
  exports.getBootcamp = asyncHandler(async (req, res, next) => {
  	const bootcamp = await Bootcamp.findById(req.params.id);
  
  	if (!bootcamp) {
  		return res.status(400).json({
  			success: false,
  		});
  	}
  
  	res.status(200).json({
  		success: true,
  		data: bootcamp,
  	});
  });
  
  // @desc    Create new bootcamp
  // @route   POST /api/v1/bootcamps
  // @access  Private
  exports.createBootcamp = asyncHandler(async (req, res, next) => {
  	req.body.user = req.user.id;
  
  	// Add logic where Publisher can pbulish only one bootcamp
  	const publishedBootcamp = await Bootcamp.findOne({ user: req.user.id });
  
  	if (publishedBootcamp && req.user.role !== "admin") {
  		return next(
  			new ErrorResponse(
  				`The user with ID ${req.user.id} has already published a bootcamp`,
  				400
  			)
  		);
  	}
  
  	const bootcamp = await Bootcamp.create(req.body);
  
  	res.status(201).json({
  		success: true,
  		data: bootcamp,
  	});
  });
  
  // @desc    Update single bootcamp
  // @route   PUT /api/v1/bootcamps/:id
  // @access  Private
  exports.updateBootcamp = asyncHandler(async (req, res, next) => {
  	let bootcamp = await Bootcamp.findById(req.params.id);
  
  	if (!bootcamp) {
  		return next(new ErrorResponse(`No bootcamps not found`, 404));
  	}
  
  	if (req.user.id !== bootcamp.user.toString() && req.user.role !== "admin") {
  		return next(
  			new ErrorResponse(
  				`User ${req.user.id} is not authorized to update this Bootcamp`,
  				401
  			)
  		);
  	}
  
  	bootcamp = await Bootcamp.findOneAndUpdate(req.params.id, req.body, {
  		new: true,
  		runValidators: true,
  	});
  
  	res.status(200).json({
  		success: true,
  		data: bootcamp,
  	});
  });
  
  // @desc    Remove single bootcamps
  // @route   DELETE /api/v1/bootcamps/:id
  // @access  Private
  exports.deleteBootcamp = asyncHandler(async (req, res, next) => {
  	const bootcamp = await Bootcamp.findById(req.params.id);
  
  	if (!bootcamp) {
  		return next(new ErrorResponse(`No bootcamps not found`, 404));
  	}
  
  	if (req.user.id !== bootcamp.user.toString() && req.user.role !== "admin") {
  		return next(
  			new ErrorResponse(
  				`User ${req.user.id} is not authorized to delete this Bootcamp`,
  				401
  			)
  		);
  	}
  
  	bootcamp.remove();
  
  	res.status(200).json({
  		success: true,
  		count: Bootcamp.length,
  		data: bootcamp,
  	});
  });
  
  // @desc    Get bootcamps withtin a radius
  // @route   GET /api/v1/bootcamps/radius/:zipcode/:distance
  // @access  Private
  exports.getBootcampsInRadius = asyncHandler(async (req, res, next) => {
  	const { zipcode, distance } = req.params;
  
  	const loc = await geocoder.geocode(zipcode);
  	const lat = loc[0].latitude;
  	const lng = loc[0].longitude;
  
  	// Calculate radius
  	const radius = distance / 3963;
  
  	// Find bootcamps within a geosphere using longi, lati and radius of the earth
  	const bootcamps = await Bootcamp.find({
  		location: { $geoWithin: { $centerSphere: [[lng, lat], radius] } },
  	});
  
  	res.status(200).json({
  		success: true,
  		count: bootcamps.length,
  		data: bootcamps,
  	});
  });
  
  // @desc    Upload Photo for Bootcamp
  // @route   PUT /api/v1/bootcamps/:id/photo
  // @access  Private
  exports.bootcampPhotoUpload = asyncHandler(async (req, res, next) => {
  	const bootcamp = await Bootcamp.findById(req.params.id);
  
  	if (!bootcamp) {
  		return next(new ErrorResponse(`No bootcamps not found`, 404));
  	}
  
  	if (req.user.id !== bootcamp.user.toString() && req.user.role !== "admin") {
  		return next(
  			new ErrorResponse(
  				`User ${req.user.id} is not authorized to update this Bootcamp`,
  				401
  			)
  		);
  	}
  
  	if (!req.files) {
  		return next(new ErrorResponse(`Please upload a file `, 404));
  	}
  
  	const file = req.files.file;
  	if (!file.mimetype.startsWith("image")) {
  		return next(new ErrorResponse(`Please upload an image file `, 404));
  	}
  
  	// Check file size
  	if (file.size > process.env.MAX_FILE_UPLOAD) {
  		return next(
  			new ErrorResponse(
  				`Please upload an image less than${process.env.MAX_FILE_UPLOAD}`,
  				404
  			)
  		);
  	}
  	file.name = `photo_${bootcamp._id}${path.parse(file.name).ext}`;
  	file.mv(`${process.env.FILE_UPLOAD_PATH}/${file.name}`, async (err) => {
  		if (err) {
  			return next(new ErrorResponse(`Problem with file upload`, 500));
  		}
  		await Bootcamp.findByIdAndUpdate(req.params.id, { photo: file.name });
  
  		res.status(200).json({
  			success: true,
  			data: file.name,
  		});
  	});
  });
  