import express from "express"; import { v4 as uuidv4 } from "uuid"; import { validate, songValidation } from "../middleware/validate.js"; const router = express.Router(); // In-memory store (replace with database in production) const songs = new Map([ [ "1", { id: "1", title: "Amazing Grace", artist: "John Newton", key: "G", originalKey: "G", tempo: 72, category: "Hymn", lyrics: `[Verse 1] [G]Amazing [D]grace, how [G]sweet the [G7]sound That [C]saved a [G]wretch like [Em]me I [G]once was [D]lost, but [G]now am [Em]found Was [G]blind but [D]now I [G]see`, createdBy: "system", createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }, ], [ "2", { id: "2", title: "How Great Is Our God", artist: "Chris Tomlin", key: "C", originalKey: "C", tempo: 78, category: "Contemporary", lyrics: `[Verse 1] The [C]splendor of the [Am]King [F]Clothed in majesty [C] Let all the earth re[Am]joice [F]All the earth re[G]joice`, createdBy: "system", createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }, ], ]); // Search songs (for worship list) router.get("/search", (req, res) => { const { q } = req.query; if (!q) { return res.json({ success: true, songs: [], total: 0, }); } const searchLower = q.toLowerCase(); const result = Array.from(songs.values()).filter( (song) => song.title.toLowerCase().includes(searchLower) || song.artist.toLowerCase().includes(searchLower), ); res.json({ success: true, songs: result, total: result.length, }); }); // Get all songs router.get("/", (req, res) => { const { search, key, category, sort } = req.query; let result = Array.from(songs.values()); // Search filter if (search) { const searchLower = search.toLowerCase(); result = result.filter( (song) => song.title.toLowerCase().includes(searchLower) || song.artist.toLowerCase().includes(searchLower), ); } // Key filter if (key) { result = result.filter((song) => song.key === key); } // Category filter if (category) { result = result.filter((song) => song.category === category); } // Sort if (sort) { const [field, order] = sort.split(":"); result.sort((a, b) => { const aVal = a[field] || ""; const bVal = b[field] || ""; const comparison = typeof aVal === "string" ? aVal.localeCompare(bVal) : aVal - bVal; return order === "desc" ? -comparison : comparison; }); } res.json({ songs: result, total: result.length, }); }); // Get single song router.get("/:id", (req, res) => { const song = songs.get(req.params.id); if (!song) { return res.status(404).json({ error: "Song not found" }); } res.json({ song }); }); // Create song router.post("/", validate(songValidation), (req, res) => { const { title, artist, key, tempo, category, lyrics } = req.body; const song = { id: uuidv4(), title, artist: artist || "Unknown", key: key || "C", originalKey: key || "C", tempo: tempo || 72, category: category || "Contemporary", lyrics: lyrics || "", createdBy: req.user.id, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; songs.set(song.id, song); res.status(201).json({ message: "Song created successfully", song, }); }); // Update song router.put("/:id", validate(songValidation), (req, res) => { const song = songs.get(req.params.id); if (!song) { return res.status(404).json({ error: "Song not found" }); } const { title, artist, key, tempo, category, lyrics } = req.body; const updatedSong = { ...song, title: title || song.title, artist: artist || song.artist, key: key || song.key, tempo: tempo || song.tempo, category: category || song.category, lyrics: lyrics !== undefined ? lyrics : song.lyrics, updatedAt: new Date().toISOString(), }; songs.set(song.id, updatedSong); res.json({ message: "Song updated successfully", song: updatedSong, }); }); // Delete song router.delete("/:id", (req, res) => { const song = songs.get(req.params.id); if (!song) { return res.status(404).json({ error: "Song not found" }); } songs.delete(req.params.id); res.json({ message: "Song deleted successfully" }); }); // Duplicate song router.post("/:id/duplicate", (req, res) => { const song = songs.get(req.params.id); if (!song) { return res.status(404).json({ error: "Song not found" }); } const duplicateSong = { ...song, id: uuidv4(), title: `${song.title} (Copy)`, createdBy: req.user.id, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; songs.set(duplicateSong.id, duplicateSong); res.status(201).json({ message: "Song duplicated successfully", song: duplicateSong, }); }); // Transpose song router.post("/:id/transpose", (req, res) => { const song = songs.get(req.params.id); if (!song) { return res.status(404).json({ error: "Song not found" }); } const { targetKey, useFlats } = req.body; // Transposition logic would go here // For now, just return the song with updated key const transposedSong = { ...song, key: targetKey || song.key, // In a real implementation, lyrics would be transposed }; res.json({ message: "Song transposed", song: transposedSong, }); }); export default router;