const express = require("express"); const Report = require("../models/Report"); const User = require("../models/User"); const Street = require("../models/Street"); const auth = require("../middleware/auth"); const { asyncHandler } = require("../middleware/errorHandler"); const { createReportValidation, reportIdValidation, } = require("../middleware/validators/reportValidator"); const { upload, handleUploadError } = require("../middleware/upload"); const { uploadImage, deleteImage } = require("../config/cloudinary"); const router = express.Router(); // Get all reports (with pagination) router.get( "/", asyncHandler(async (req, res) => { const page = parseInt(req.query.page) || 1; const limit = Math.min(parseInt(req.query.limit) || 10, 100); const result = await Report.findWithPagination({ page, limit, sort: { createdAt: -1 }, }); res.json({ reports: result.docs, totalCount: result.totalDocs, currentPage: result.page, totalPages: result.totalPages, hasNext: result.hasNextPage, hasPrev: result.hasPrevPage, }); }), ); // Create a report with optional image router.post( "/", auth, upload.single("image"), handleUploadError, createReportValidation, asyncHandler(async (req, res) => { const { street: streetId, issue } = req.body; // Get street and user data for embedding const street = await Street.findById(streetId); if (!street) { return res.status(404).json({ msg: "Street not found" }); } const user = await User.findById(req.user.id); if (!user) { return res.status(404).json({ msg: "User not found" }); } const reportData = { street: { _id: street._id, name: street.name, }, user: { _id: user._id, name: user.name, profilePicture: user.profilePicture, }, issue, }; // Upload image if provided if (req.file) { const result = await uploadImage( req.file.buffer, "adopt-a-street/reports", ); reportData.imageUrl = result.url; reportData.cloudinaryPublicId = result.publicId; } const report = await Report.create(reportData); res.json(report); }), ); // Add image to existing report router.post( "/:id/image", auth, upload.single("image"), handleUploadError, reportIdValidation, asyncHandler(async (req, res) => { const report = await Report.findById(req.params.id); if (!report) { return res.status(404).json({ msg: "Report not found" }); } // Verify user owns the report if (report.user._id !== req.user.id) { return res.status(403).json({ msg: "Not authorized" }); } if (!req.file) { return res.status(400).json({ msg: "No image file provided" }); } // Delete old image if exists if (report.cloudinaryPublicId) { await deleteImage(report.cloudinaryPublicId); } // Upload new image const result = await uploadImage( req.file.buffer, "adopt-a-street/reports", ); const updatedReport = await Report.update(req.params.id, { imageUrl: result.url, cloudinaryPublicId: result.publicId, }); res.json(updatedReport); }), ); // Resolve a report router.put( "/:id", auth, reportIdValidation, asyncHandler(async (req, res) => { const report = await Report.findById(req.params.id); if (!report) { return res.status(404).json({ msg: "Report not found" }); } const updatedReport = await Report.update(req.params.id, { status: "resolved", }); res.json(updatedReport); }), ); module.exports = router;