const express = require('express'); const router = express.Router(); const path = require('path'); const multer = require('multer'); const fs = require('fs'); const tools = require('../tools/general'); const { Contribtype } = require('../models/contribtype'); // Adatta al tuo path // Import Controllers const rideController = require('../controllers/rideController'); const rideRequestController = require('../controllers/rideRequestController'); const chatController = require('../controllers/chatController'); const feedbackController = require('../controllers/feedbackController'); // const geocodingController = require('../controllers/geocodingController'); const geoRoutes = require('./geoRoutes'); // πŸ‘ˆ Importa geoRoutes router.use('/geo', geoRoutes); // πŸ‘ˆ Monta come sub-router // Middleware di autenticazione (usa il tuo esistente) const { authenticate } = require('../middleware/authenticate'); // ============================================================ // πŸš— RIDES - Gestione Viaggi // ============================================================ /** * @route POST /api/viaggi/rides * @desc Crea nuovo viaggio (offerta o richiesta) * @access Private */ router.post('/rides', authenticate, rideController.createRide); /** * @route GET /api/viaggi/rides * @desc Ottieni lista viaggi con filtri * @access Public */ router.get('/rides', rideController.getRides); /** * @route GET /api/viaggi/rides/search * @desc Ricerca viaggi avanzata * @access Public */ router.get('/rides/search', rideController.searchRides); /** * @route GET /api/viaggi/rides/stats * @desc Statistiche per widget homepage * @access Private */ router.get('/rides/stats', authenticate, rideController.getRidesStats); /** * @route GET /api/viaggi/rides/my * @desc I miei viaggi (come driver e passenger) * @access Private */ router.get('/rides/my', authenticate, rideController.getMyRides); /** * @route GET /api/viaggi/rides/match * @desc Match automatico offerta/richiesta * @access Private * @note ⚠️ IMPORTANTE: Questa route DEVE stare PRIMA di /rides/:id */ //router.get('/rides/match', authenticate, rideController.findMatches); router.get('/rides/cancelled', authenticate, rideController.getCancelledRides); router.get('/rides/statscomm', authenticate, rideController.getCommunityStatsComm); router.get('/rides/community', authenticate, rideController.getCommunityRides); router.get('/rides/calendar', authenticate, rideController.getCalendarRides); /** * @route POST /api/viaggi/rides/:rideId/request * @desc Richiedi posto su un viaggio * @access Private */ router.post('/rides/:rideId/request', authenticate, rideRequestController.createRequestFromRide); /** * @route GET /api/viaggi/rides/:id * @desc Dettaglio singolo viaggio * @access Public */ router.get('/rides/:id', rideController.getRideById); /** * @route PUT /api/viaggi/rides/:id * @desc Aggiorna viaggio * @access Private (solo owner) */ router.put('/rides/:id', authenticate, rideController.updateRide); /** * @route DELETE /api/viaggi/rides/:id * @desc Cancella viaggio * @access Private (solo owner) */ router.delete('/rides/:id', authenticate, rideController.deleteRide); /** * @route POST /api/viaggi/rides/:id/complete * @desc Completa un viaggio * @access Private (solo driver) */ router.post('/rides/:id/complete', authenticate, rideController.completeRide); router.post('/rides/:rideId/favorite', authenticate, rideController.toggleFavoriteRide); // ============================================================ // πŸ“Š WIDGET & STATS // ============================================================ /** * @route GET /api/viaggi/widget/data * @desc Dati completi per widget homepage * @access Private */ router.get('/widget/data', authenticate, rideController.getWidgetData); /** * @route GET /api/viaggi/cities/suggestions * @desc Suggerimenti cittΓ  per autocomplete (basato su viaggi esistenti) * @access Public */ router.get('/cities/suggestions', rideController.getCitySuggestions); /** * @route GET /api/viaggi/cities/recents * @desc cittΓ  recenti per autocomplete * @access Public */ router.get('/cities/recent', authenticate, rideController.getRecentCities); // ============================================================ // πŸ“© REQUESTS - Richieste Passaggio // ============================================================ /** * @route POST /api/viaggi/requests * @desc Crea richiesta passaggio per un viaggio * @access Private */ router.post('/requests', authenticate, rideRequestController.createRequest); // ⚠️ IMPORTANTE: Route specifiche PRIMA di quelle con :id /** * @route GET /api/viaggi/requests/received * @desc Richieste ricevute (sono conducente) * @access Private */ router.get('/requests/received', authenticate, rideRequestController.getReceivedRequests); /** * @route GET /api/viaggi/requests/sent * @desc Richieste inviate (sono passeggero) * @access Private */ router.get('/requests/sent', authenticate, rideRequestController.getSentRequests); /** * @route GET /api/viaggi/requests/pending * @desc Richieste pendenti (per il conducente) * @access Private */ router.get('/requests/pending', authenticate, rideRequestController.getPendingRequests); /** * @route GET /api/viaggi/requests/my * @desc Le mie richieste (come passeggero) * @access Private */ router.get('/requests/my', authenticate, rideRequestController.getMyRequests); /** * @route GET /api/viaggi/requests/ride/:rideId * @desc Richieste per un viaggio specifico * @access Private (solo owner del viaggio) */ router.get('/requests/ride/:rideId', authenticate, rideRequestController.getRequestsForRide); // ⚠️ Route con :id DOPO tutte le route specifiche /** * @route GET /api/viaggi/requests/:id * @desc Dettaglio singola richiesta * @access Private (driver o passenger) */ router.get('/requests/:id', authenticate, rideRequestController.getRequestById); /** * @route POST /api/viaggi/requests/:id/accept * @desc Accetta richiesta passaggio * @access Private (solo driver) */ router.post('/requests/:id/accept', authenticate, rideRequestController.acceptRequest); /** * @route POST /api/viaggi/requests/:id/reject * @desc Rifiuta richiesta passaggio * @access Private (solo driver) */ router.post('/requests/:id/reject', authenticate, rideRequestController.rejectRequest); /** * @route POST /api/viaggi/requests/:id/cancel * @desc Cancella richiesta/prenotazione * @access Private (driver o passenger) */ router.post('/requests/:id/cancel', authenticate, rideRequestController.cancelRequest); // ============================================================ // πŸ’¬ CHAT - Messaggistica // ============================================================ /** * @route GET /api/viaggi/chats * @desc Lista tutte le mie chat * @access Private */ router.get('/chats', authenticate, chatController.getUserChats); /** * @route GET /api/viaggi/chats/unread/count * @desc Conta messaggi non letti totali * @access Private */ router.get('/chats/unread/count', authenticate, chatController.getUnreadCount); /** * @route POST /api/viaggi/chats/direct * @desc Ottieni o crea chat diretta con utente * @access Private */ router.post('/chats/direct', authenticate, chatController.getOrCreateDirectChat); /** * @route GET /api/viaggi/chats/:id * @desc Dettaglio chat * @access Private (solo partecipanti) */ router.get('/chats/:chatId', authenticate, chatController.getChatById); /** * @route GET /api/viaggi/chats/:id/messages * @desc Messaggi di una chat * @access Private (solo partecipanti) */ router.get('/chats/:chatId/messages', authenticate, chatController.getChatMessages); /** * @route POST /api/viaggi/chats/:id/messages * @desc Invia messaggio * @access Private (solo partecipanti) */ router.post('/chats/:chatId/messages', authenticate, chatController.sendMessage); /** * @route PUT /api/viaggi/chats/:id/read * @desc Segna chat come letta * @access Private (solo partecipanti) * @fix Corretto: markAsRead β†’ markChatAsRead */ router.put('/chats/:chatId/read', authenticate, chatController.markChatAsRead); /** * @route PUT /api/viaggi/chats/:id/block * @desc Blocca/sblocca chat * @access Private (solo partecipanti) */ router.put('/chats/:chatId/block', authenticate, chatController.toggleBlockChat); /** * @route PUT /api/viaggi/chats/:id/mute * @desc Muta/smuta notifiche di una chat * @access Private (solo partecipanti) * @fix Aggiunta route mancante */ router.put('/chats/:chatId/mute', authenticate, chatController.toggleMuteChat); /** * @route DELETE /api/viaggi/chats/:chatId/messages/:messageId * @desc Elimina messaggio * @access Private (solo mittente) * @fix Corretto: /messages/:id β†’ /chats/:chatId/messages/:messageId */ router.delete('/chats/:chatId/messages/:messageId', authenticate, chatController.deleteMessage); /** * @route DELETE /api/viaggi/chats/:id * @desc Elimina chat (soft delete) * @access Private (solo partecipanti) */ router.delete('/chats/:chatId', authenticate, chatController.deleteChat); // ============================================================ // ⭐ FEEDBACK - Recensioni // ============================================================ /** * @route POST /api/viaggi/feedback * @desc Crea feedback per un viaggio * @access Private */ router.post('/feedback', authenticate, feedbackController.createFeedback); /** * @route GET /api/viaggi/feedback/my/received * @desc I miei feedback ricevuti * @access Private */ router.get('/feedback/my/received', authenticate, feedbackController.getMyReceivedFeedbacks); /** * @route GET /api/viaggi/feedback/my/given * @desc I miei feedback lasciati * @access Private */ router.get('/feedback/my/given', authenticate, feedbackController.getMyGivenFeedbacks); /** * @route GET /api/viaggi/feedback/user/:userId * @desc Feedback di un utente * @access Public */ router.get('/feedback/user/:userId', feedbackController.getFeedbacksForUser); /** * @route GET /api/viaggi/feedback/user/:userId/stats * @desc Statistiche feedback utente * @access Public */ router.get('/feedback/user/:userId/stats', feedbackController.getUserFeedbackStats); /** * @route GET /api/viaggi/feedback/ride/:rideId * @desc Feedback per un viaggio * @access Public */ router.get('/feedback/ride/:rideId', feedbackController.getRideFeedback); /** * @route GET /api/viaggi/feedback/can-leave/:rideId/:toUserId * @desc Verifica se posso lasciare feedback * @access Private */ router.get('/feedback/can-leave/:rideId/:toUserId', authenticate, feedbackController.canLeaveFeedback); /** * @route POST /api/viaggi/feedback/:id/response * @desc Rispondi a un feedback * @access Private (solo destinatario) */ router.post('/feedback/:id/response', authenticate, feedbackController.respondToFeedback); /** * @route POST /api/viaggi/feedback/:id/report * @desc Segnala feedback * @access Private */ router.post('/feedback/:id/report', authenticate, feedbackController.reportFeedback); /** * @route POST /api/viaggi/feedback/:id/helpful * @desc Segna feedback come utile * @access Private */ router.post('/feedback/:id/helpful', authenticate, feedbackController.markAsHelpful); // ============================================================ // πŸ—ΊοΈ GEO - Geocoding & Mappe (Open Source) // ============================================================ // /* /** // * @route GET /api/viaggi/geo/autocomplete // * @desc Autocomplete cittΓ  (Photon) // * @access Public // */ // router.get('/geo/autocomplete', geocodingController.autocomplete); // /** // * @route GET /api/viaggi/geo/cities/it // * @desc Cerca cittΓ  italiane // * @access Public // */ // router.get('/geo/cities/it', geocodingController.searchItalianCities); // /** // * @route GET /api/viaggi/geo/geocode // * @desc Indirizzo β†’ Coordinate // * @access Public // */ // router.get('/geo/geocode', geocodingController.geocode); // /** // * @route GET /api/viaggi/geo/reverse // * @desc Coordinate β†’ Indirizzo // * @access Public // */ // router.get('/geo/reverse', geocodingController.reverseGeocode); // /** // * @route GET /api/viaggi/geo/route // * @desc Calcola percorso tra punti // * @access Public // */ // router.get('/geo/route', geocodingController.getRoute); // /** // * @route GET /api/viaggi/geo/distance // * @desc Calcola distanza e durata // * @access Public // */ // router.get('/geo/distance', geocodingController.getDistance); // /** // * @route GET /api/viaggi/geo/suggest-waypoints // * @desc Suggerisci cittΓ  intermedie sul percorso // * @access Public // */ // router.get('/geo/suggest-waypoints', geocodingController.suggestWaypoints); /// ============================================================ // πŸ”§ UTILITY & DRIVER PROFILE // ============================================================ /** * @route GET /api/viaggi/driver/user/:userId * @desc Profilo pubblico del conducente * @access Public */ router.get('/driver/user/:userId', async (req, res) => { try { const { userId } = req.params; const idapp = req.query.idapp; const { User } = require('../models/user'); const Ride = require('../models/viaggi/Ride'); const Feedback = require('../models/viaggi/Feedback'); // Dati utente const user = await User.findById(userId).select( 'username name surname profile.img profile.Biografia profile.driverProfile profile.preferences.languages' ); if (!user) { return res.status(404).json({ success: false, message: 'Utente non trovato', }); } // Statistiche viaggi const [ridesAsDriver, ridesAsPassenger, completedRides] = await Promise.all([ Ride.countDocuments({ idapp, userId, type: 'offer' }), Ride.countDocuments({ idapp, 'confirmedPassengers.userId': userId }), Ride.countDocuments({ idapp, userId, status: 'completed' }), ]); // Ultimi viaggi come driver const recentRides = await Ride.find({ idapp, userId, type: 'offer', status: { $in: ['active', 'completed'] }, }) .select('departure destination departureDate status') .sort({ departureDate: -1 }) .limit(5); // Statistiche feedback let feedbackStats = { averageRating: 0, totalFeedback: 0 }; try { feedbackStats = await Feedback.getStatsForUser(idapp, userId); } catch (e) { console.log('Feedback stats non disponibili'); } // Ultimi feedback ricevuti let recentFeedback = []; try { recentFeedback = await Feedback.find({ idapp, toUserId: userId, isPublic: true, }) .populate('fromUserId', 'username name profile.img') .sort({ createdAt: -1 }) .limit(3); } catch (e) { console.log('Recent feedback non disponibili'); } res.status(200).json({ success: true, data: { user: { _id: user._id, username: user.username, name: user.name, surname: user.surname, img: user.profile?.img, bio: user.profile?.Biografia, driverProfile: user.profile?.driverProfile, languages: user.profile?.preferences?.languages, }, stats: { ridesAsDriver, ridesAsPassenger, completedRides, ...feedbackStats, }, recentRides, recentFeedback, }, }); } catch (error) { console.error('Errore recupero profilo driver:', error); res.status(500).json({ success: false, message: 'Errore durante il recupero del profilo', error: error.message, }); } }); /** * @route GET /api/viaggi/driver/vehicles * @desc Ottieni veicoli dell'utente corrente * @access Private */ router.get('/driver/vehicles', authenticate, async (req, res) => { try { const idapp = req.user.idapp; const userId = req.user._id; // Assumo che ci sia un middleware di autenticazione if (!userId) { return res.status(401).json({ success: false, message: 'Autenticazione richiesta', }); } const { User } = require('../models/user'); const user = await User.findById(userId).select('profile.driverProfile.vehicles'); const vehicles = user?.profile?.driverProfile?.vehicles || []; res.status(200).json({ success: true, data: vehicles, }); } catch (error) { console.error('Errore recupero veicoli:', error); res.status(500).json({ success: false, message: 'Errore durante il recupero dei veicoli', error: error.message, }); } }); /** * @route PUT /api/viaggi/driver/profile * @desc Aggiorna profilo conducente * @access Private */ router.put('/driver/profile', authenticate, async (req, res) => { try { const userId = req.user._id; const { idapp, driverProfile, preferences } = req.body; const { User } = require('../models/user'); const updateData = {}; if (driverProfile) { // Merge con dati esistenti Object.keys(driverProfile).forEach((key) => { updateData[`profile.driverProfile.${key}`] = driverProfile[key]; }); } if (preferences) { Object.keys(preferences).forEach((key) => { updateData[`profile.preferences.${key}`] = preferences[key]; }); } const user = await User.findByIdAndUpdate(userId, { $set: updateData }, { new: true }).select( 'profile.driverProfile profile.preferences' ); res.status(200).json({ success: true, message: 'Profilo aggiornato', data: user.profile, }); } catch (error) { console.error('Errore aggiornamento profilo:', error); res.status(500).json({ success: false, message: "Errore durante l'aggiornamento", error: error.message, }); } }); /** * @route POST /api/viaggi/driver/vehicles * @desc Aggiungi veicolo * @access Private */ router.post('/driver/vehicles', authenticate, async (req, res) => { try { const userId = req.user._id; const vehicle = req.body.vehicle ? req.body.vehicle : req.body; const { User } = require('../models/user'); const user = await User.findByIdAndUpdate( userId, { $push: { 'profile.driverProfile.vehicles': vehicle }, $set: { 'profile.driverProfile.isDriver': true }, }, { new: true } ).select('profile.driverProfile.vehicles'); res.status(201).json({ success: true, message: 'Veicolo aggiunto', data: user.profile.driverProfile.vehicles, }); } catch (error) { console.error('Errore aggiunta veicolo:', error); res.status(500).json({ success: false, message: "Errore durante l'aggiunta del veicolo", error: error.message, }); } }); /** * @route PUT /api/viaggi/driver/vehicles/:vehicleId * @desc Aggiorna veicolo * @access Private */ router.put('/driver/vehicles/:vehicleId', authenticate, async (req, res) => { try { const userId = req.user._id; const { vehicleId } = req.params; const vehicle = req.body; const { User } = require('../models/user'); const user = await User.findOneAndUpdate( { _id: userId, 'profile.driverProfile.vehicles._id': vehicleId, }, { $set: { 'profile.driverProfile.vehicles.$': { ...vehicle, _id: vehicleId } }, }, { new: true } ).select('profile.driverProfile.vehicles'); if (!user) { return res.status(404).json({ success: false, message: 'Veicolo non trovato', }); } res.status(200).json({ success: true, message: 'Veicolo aggiornato', data: user.profile.driverProfile.vehicles, }); } catch (error) { console.error('Errore aggiornamento veicolo:', error); res.status(500).json({ success: false, message: "Errore durante l'aggiornamento", error: error.message, }); } }); /** * @route GET /api/viaggi/driver/vehicles/:vehicleId * @desc Ottieni dettagli di un veicolo specifico * @access Private */ router.get('/driver/vehicles/:vehicleId', authenticate, async (req, res) => { try { const userId = req.user._id; const { vehicleId } = req.params; const { User } = require('../models/user'); const user = await User.findOne({ _id: userId, 'profile.driverProfile.vehicles._id': vehicleId, }).select('profile.driverProfile.vehicles'); if (!user) { return res.status(404).json({ success: false, message: 'Veicolo non trovato', }); } // Trova il veicolo specifico nell'array const vehicle = user.profile.driverProfile.vehicles.find((v) => v._id.toString() === vehicleId); if (!vehicle) { return res.status(404).json({ success: false, message: 'Veicolo non trovato', }); } res.status(200).json({ success: true, data: vehicle, }); } catch (error) { console.error('Errore recupero veicolo:', error); res.status(500).json({ success: false, message: 'Errore durante il recupero del veicolo', error: error.message, }); } }); /** * @route DELETE /api/viaggi/driver/vehicles/:vehicleId * @desc Rimuovi veicolo * @access Private */ router.delete('/driver/vehicles/:vehicleId', authenticate, async (req, res) => { try { const userId = req.user._id; const { vehicleId } = req.params; const { User } = require('../models/user'); await User.findByIdAndUpdate(userId, { $pull: { 'profile.driverProfile.vehicles': { _id: vehicleId } }, }); res.status(200).json({ success: true, message: 'Veicolo rimosso', }); } catch (error) { console.error('Errore rimozione veicolo:', error); res.status(500).json({ success: false, message: 'Errore durante la rimozione', error: error.message, }); } }); /** * @route POST /api/viaggi/driver/vehicles/:vehicleId/default * @desc Imposta veicolo come predefinito * @access Private */ router.post('/driver/vehicles/:vehicleId/default', authenticate, async (req, res) => { try { const userId = req.user._id; const { vehicleId } = req.params; const { User } = require('../models/user'); // Prima rimuovi isDefault da tutti await User.updateOne({ _id: userId }, { $set: { 'profile.driverProfile.vehicles.$[].isDefault': false } }); // Poi imposta quello selezionato await User.updateOne( { _id: userId, 'profile.driverProfile.vehicles._id': vehicleId }, { $set: { 'profile.driverProfile.vehicles.$.isDefault': true } } ); res.status(200).json({ success: true, message: 'Veicolo predefinito impostato', }); } catch (error) { console.error('Errore impostazione default:', error); res.status(500).json({ success: false, message: "Errore durante l'operazione", error: error.message, }); } }); // ============================================================ // πŸ“Š CONTRIB TYPES - Tipi di Contributo // ============================================================ /** * @route GET /api/viaggi/contrib-types * @desc Lista tipi di contributo disponibili * @access Public */ router.get('/contrib-types', async (req, res) => { try { const idapp = req.query.idapp; const contribTypes = await Contribtype.find({ idapp }); res.status(200).json({ success: true, data: contribTypes, }); } catch (error) { console.error('Errore recupero contrib types:', error); res.status(500).json({ success: false, message: 'Errore durante il recupero', error: error.message, }); } }); const vehiclePhotoStorage = multer.diskStorage({ destination: (req, file, cb) => { const webServerDir = tools.getdirByIdApp(req.user.idapp) + '/upload/vehicles'; if (!fs.existsSync(webServerDir)) { fs.mkdirSync(webServerDir, { recursive: true }); } console.log('πŸ“ Destinazione foto veicolo:', webServerDir); cb(null, webServerDir); }, filename: (req, file, cb) => { const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9); const ext = path.extname(file.originalname); const filename = 'vehicle-' + uniqueSuffix + ext; console.log('πŸ“ Nome file generato:', filename); cb(null, filename); }, }); const uploadVehiclePhoto = multer({ storage: vehiclePhotoStorage, limits: { fileSize: 5 * 1024 * 1024, // 5MB }, fileFilter: (req, file, cb) => { console.log('πŸ” File ricevuto:', { fieldname: file.fieldname, originalname: file.originalname, mimetype: file.mimetype, }); const allowedMimes = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp', 'image/gif']; if (allowedMimes.includes(file.mimetype)) { cb(null, true); } else { cb(new Error('Solo immagini sono ammesse'), false); } }, }); /** * @route POST /api/viaggi/upload/vehicle-photos * @desc Upload multiple foto veicolo (max 5) * @access Private */ router.post( '/upload/vehicle-photos', authenticate, (req, res, next) => { console.log('πŸš€ Request ricevuta per upload multiple foto veicolo'); next(); }, uploadVehiclePhoto.array('photos', 5), (err, req, res, next) => { if (err) { console.error('❌ Errore multer:', err); return res.status(400).json({ success: false, message: err.message || 'Errore durante upload', }); } next(); }, async (req, res) => { try { console.log('βœ… Files ricevuti:', req.files); if (!req.files || req.files.length === 0) { return res.status(400).json({ success: false, message: 'Nessuna foto caricata', }); } const photoUrls = req.files.map((file) => `/upload/vehicles/${file.filename}`); res.status(200).json({ success: true, message: `${req.files.length} foto caricate con successo`, data: { urls: photoUrls, count: req.files.length, }, }); } catch (error) { console.error('❌ Errore upload foto veicolo:', error); // Elimina tutti i file in caso di errore if (req.files && req.files.length > 0) { req.files.forEach((file) => { if (file.path) { fs.unlinkSync(file.path); } }); } res.status(500).json({ success: false, message: "Errore durante l'upload delle foto", error: error.message, }); } } ); /** * @route POST /api/viaggi/upload/vehicle-photo * @desc Upload foto veicolo * @access Private */ router.post( '/upload/vehicle-photo', authenticate, (req, res, next) => { console.log('πŸš€ Request ricevuta per upload foto veicolo'); console.log('πŸ“‹ Headers:', req.headers); console.log('πŸ“¦ Body type:', typeof req.body); next(); }, uploadVehiclePhoto.single('photo'), (err, req, res, next) => { // Gestione errori multer if (err) { console.error('❌ Errore multer:', err); return res.status(400).json({ success: false, message: err.message || 'Errore durante upload', }); } next(); }, async (req, res) => { try { console.log('βœ… File ricevuto:', req.file); console.log('πŸ“„ Body:', req.body); if (!req.file) { return res.status(400).json({ success: false, message: 'Nessuna foto caricata - req.file Γ¨ undefined', }); } const photoUrl = `/upload/vehicles/${req.file.filename}`; res.status(200).json({ success: true, message: 'Foto caricata con successo', data: { url: photoUrl, filename: req.file.filename, }, }); } catch (error) { console.error('❌ Errore upload foto veicolo:', error); if (req.file && req.file.path) { fs.unlinkSync(req.file.path); } res.status(500).json({ success: false, message: "Errore durante l'upload della foto", error: error.message, }); } } ); /** * @route DELETE /api/viaggi/upload/vehicle-photo * @desc Elimina foto veicolo * @access Private */ router.delete('/upload/vehicle-photo', authenticate, async (req, res) => { try { const { photoUrl } = req.body; if (!photoUrl) { return res.status(400).json({ success: false, message: 'URL foto non fornito', }); } // Estrai il filename dall'URL const filename = photoUrl.split('/').pop(); const filepath = path.join(vehiclesDir, filename); // Verifica che il file esista if (fs.existsSync(filepath)) { fs.unlinkSync(filepath); } res.status(200).json({ success: true, message: 'Foto eliminata con successo', }); } catch (error) { console.error('❌ Errore eliminazione foto:', error); res.status(500).json({ success: false, message: "Errore durante l'eliminazione della foto", error: error.message, }); } }); // ============================================ // EXPORT ROUTES // ============================================ module.exports = router;