const express = require('express'); const mongoose = require('mongoose'); const router = express.Router(); const User = require('./user'); const multer = require('multer'); const path = require('path'); // Configuración de almacenamiento para música const storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, 'uploads/music'); }, filename: function (req, file, cb) { const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9); cb(null, uniqueSuffix + path.extname(file.originalname)); } }); const upload = multer({ storage: storage, limits: { fileSize: 10 * 1024 * 1024 }, // máx 10MB fileFilter: function (req, file, cb) { if (!file.originalname.match(/\.(mp3)$/)) { return cb(new Error('Solo se permiten archivos .mp3')); } cb(null, true); } }); const routineSchema = new mongoose.Schema({ title: String, createdBy: { type: String, default: "coach-id-ejemplo" }, language: { type: String, enum: ['es', 'en', 'fr'], default: 'es' }, duration: Number, musicUrl: { type: String, default: "" }, nombreCompetencia: String, tipoCompetencia: { type: String, enum: ['libre', 'técnica'], default: 'libre' }, modalidad: { type: String, enum: ['solo', 'duo', 'equipo'], default: 'solo' }, participantes: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }], elements: [], formaciones: [ { nombreColoquial: String, notasTacticas: String, duracion: Number, atletas: [ { atletaId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }, idPersonalizado: String, x: Number, y: Number, rol: String, grupo: String, direccion: { x1: Number, y1: Number, x2: Number, y2: Number }, figura: String, tipoElemento: { type: String, enum: ['TRE', 'híbrido', 'transición'], default: 'transición' }, codigoElemento: String } ] } ], createdAt: { type: Date, default: Date.now } }); const Routine = mongoose.model('Routine', routineSchema); // GET todas las rutinas router.get('/', async (req, res) => { try { const routines = await Routine.find() .populate('participantes', 'name') .populate('formaciones.atletas.atletaId', 'name'); res.json(routines); } catch (error) { res.status(500).json({ message: 'Error al obtener rutinas', error }); } }); // POST nueva rutina router.post('/', async (req, res) => { try { const newRoutine = new Routine(req.body); await newRoutine.save(); res.status(201).json({ message: 'Rutina guardada exitosamente', routine: newRoutine }); } catch (error) { res.status(500).json({ message: 'Error al guardar la rutina', error }); } }); // GET rutina por ID router.get('/:id', async (req, res) => { try { const routine = await Routine.findById(req.params.id) .populate('participantes', 'name') .populate('formaciones.atletas.atletaId', 'name'); if (!routine) return res.status(404).json({ error: 'Rutina no encontrada' }); res.json(routine); } catch (error) { res.status(500).json({ error: 'Error al cargar rutina', details: error }); } }); // POST agregar formación router.post('/:id/formations', async (req, res) => { const { id } = req.params; if (!mongoose.Types.ObjectId.isValid(id)) { return res.status(400).json({ error: 'ID inválido para rutina' }); } try { const rutina = await Routine.findById(id); if (!rutina) return res.status(404).json({ error: 'Rutina no encontrada' }); rutina.formaciones.push(req.body); await rutina.save(); res.status(200).json({ message: 'Formación agregada exitosamente' }); } catch (error) { res.status(500).json({ error: 'Error al guardar formación', details: error }); } }); // GET formaciones de rutina router.get('/:id/formations', async (req, res) => { try { const rutina = await Routine.findById(req.params.id) .populate('formaciones.atletas.atletaId', 'name'); if (!rutina) return res.status(404).json({ error: 'Rutina no encontrada' }); res.status(200).json(rutina.formaciones); } catch (error) { res.status(500).json({ error: 'Error al obtener formaciones', details: error }); } }); // PUT editar formación por índice router.put('/:id/formations/:index', async (req, res) => { const { id, index } = req.params; if (!mongoose.Types.ObjectId.isValid(id)) { return res.status(400).json({ error: 'ID inválido' }); } const i = parseInt(index); if (isNaN(i) || i < 0) { return res.status(400).json({ error: 'Índice de formación inválido' }); } try { const rutina = await Routine.findById(id); if (!rutina) return res.status(404).json({ error: 'Rutina no encontrada' }); rutina.formaciones[i] = req.body; await rutina.save(); res.status(200).json({ message: 'Formación actualizada correctamente' }); } catch (error) { res.status(500).json({ error: 'Error al actualizar formación', details: error }); } }); // POST para actualizar tamaño de piscina router.post('/:id/piscina', async (req, res) => { const { width, height } = req.body; try { const updated = await Routine.findByIdAndUpdate( req.params.id, { $set: { 'piscina.width': width, 'piscina.height': height } }, { new: true } ); if (!updated) return res.status(404).json({ message: 'Rutina no encontrada' }); res.json({ message: 'Piscina actualizada', rutina: updated }); } catch (error) { res.status(500).json({ message: 'Error al actualizar piscina', error }); } }); // PUT actualizar todas las formaciones (reordenamiento) router.put('/:id', async (req, res) => { const { id } = req.params; const { formaciones } = req.body; try { const rutina = await Routine.findById(id); if (!rutina) return res.status(404).json({ error: 'Rutina no encontrada' }); rutina.formaciones = formaciones; await rutina.save(); res.status(200).json({ message: 'Formaciones reordenadas correctamente' }); } catch (error) { res.status(500).json({ message: 'Error al actualizar orden', error }); } }); // POST subir música MP3 router.post('/upload/music', upload.single('music'), (req, res) => { if (!req.file) { return res.status(400).json({ error: 'No se subió ningún archivo' }); } const fileUrl = `/uploads/music/${req.file.filename}`; res.status(200).json({ url: fileUrl }); }); module.exports = router;