const express = require("express"); const Street = require("../models/Street"); const User = require("../models/User"); const couchdbService = require("../services/couchdbService"); const auth = require("../middleware/auth"); const { asyncHandler } = require("../middleware/errorHandler"); const { createStreetValidation, streetIdValidation, } = require("../middleware/validators/streetValidator"); const router = express.Router(); // Get all streets (with pagination) router.get( "/", asyncHandler(async (req, res) => { const { buildPaginatedResponse } = require("../middleware/pagination"); // Parse pagination params const page = parseInt(req.query.page) || 1; const limit = Math.min(parseInt(req.query.limit) || 10, 100); const skip = (page - 1) * limit; const streets = await Street.find({ sort: [{ name: "asc" }], skip, limit }); // Populate adoptedBy information for (const street of streets) { if (street.adoptedBy && street.adoptedBy.userId) { await street.populate("adoptedBy"); } } const totalCount = await Street.countDocuments(); res.json(buildPaginatedResponse(streets, totalCount, page, limit)); }), ); // Get single street router.get( "/:id", streetIdValidation, asyncHandler(async (req, res) => { const street = await Street.findById(req.params.id); if (!street) { return res.status(404).json({ msg: "Street not found" }); } // Populate adoptedBy information if exists if (street.adoptedBy && street.adoptedBy.userId) { await street.populate("adoptedBy"); } res.json(street); }), ); // Create a street router.post( "/", auth, createStreetValidation, asyncHandler(async (req, res) => { const { name, location } = req.body; const street = await Street.create({ name, location, }); res.json(street); }), ); // Adopt a street router.put( "/adopt/:id", auth, streetIdValidation, asyncHandler(async (req, res) => { try { await couchdbService.initialize(); const street = await Street.findById(req.params.id); if (!street) { return res.status(404).json({ msg: "Street not found" }); } if (street.status === "adopted") { return res.status(400).json({ msg: "Street already adopted" }); } // Check if user has already adopted this street const user = await User.findById(req.user.id); if (user.adoptedStreets.includes(req.params.id)) { return res .status(400) .json({ msg: "You have already adopted this street" }); } // Get user details for embedding const userDetails = { userId: user._id, name: user.name, profilePicture: user.profilePicture || '' }; // Update street street.adoptedBy = userDetails; street.status = "adopted"; await street.save(); // Update user's adoptedStreets array user.adoptedStreets.push(street._id); user.stats.streetsAdopted = user.adoptedStreets.length; await user.save(); // Award points for street adoption using CouchDB service const updatedUser = await couchdbService.updateUserPoints( req.user.id, 50, 'Street adoption', { entityType: 'Street', entityId: street._id, entityName: street.name } ); res.json({ street, pointsAwarded: 50, newBalance: updatedUser.points, badgesEarned: [], // Badges are handled automatically in CouchDB service }); } catch (err) { console.error("Error adopting street:", err.message); throw err; } }), ); module.exports = router;