const express = require("express"); const router = express.Router(); const db = require("../database/database"); /* ======================== Auth Middleware ======================== */ function requireLogin(req, res, next) { if (!req.session.user) return res.status(401).json({ error: "Nicht eingeloggt" }); next(); } router.use(requireLogin); /* ════════════════════════════════════════════ GET /api/card-groups Alle Kartengruppen ════════════════════════════════════════════ */ router.get("/card-groups", async (req, res) => { try { const [groups] = await db.query("SELECT * FROM card_groups ORDER BY id"); res.json(groups); } catch (err) { console.error(err); res.status(500).json({ error: "DB Fehler" }); } }); /* ════════════════════════════════════════════ GET /api/cards?group_id=X&page=Y&limit=Z Alle Karten (Admin-/Gruppen-Ansicht, kein Besitz) ════════════════════════════════════════════ */ router.get("/cards", async (req, res) => { const { group_id, page = 1, limit = 12 } = req.query; const offset = (page - 1) * limit; try { const [cards] = await db.query( `SELECT c.*, cg.name AS group_name, cg.color AS group_color, c.attack, c.defends, c.cooldown, c.\`range\`, c.\`race\` FROM cards c LEFT JOIN card_groups cg ON cg.id = c.group_id WHERE c.group_id = ? LIMIT ? OFFSET ?`, [group_id, parseInt(limit), parseInt(offset)] ); const [[{ total }]] = await db.query( "SELECT COUNT(*) AS total FROM cards WHERE group_id = ?", [group_id] ); res.json({ cards, total, page: parseInt(page), totalPages: Math.ceil(total / limit) }); } catch (err) { console.error(err); res.status(500).json({ error: "DB Fehler" }); } }); /* ════════════════════════════════════════════ GET /api/user-cards?group_id=X&page=Y&limit=Z Karten die der Spieler besitzt (mit amount) ════════════════════════════════════════════ */ router.get("/user-cards", async (req, res) => { const userId = req.session.user.id; const { group_id, page = 1, limit = 18 } = req.query; const offset = (page - 1) * limit; try { const [cards] = await db.query( `SELECT uc.card_id, uc.amount, c.name, c.image, c.rarity, cg.name AS group_name, cg.color AS group_color, c.attack, c.defends, c.cooldown, c.\`range\`, c.\`race\` FROM user_cards uc JOIN cards c ON c.id = uc.card_id JOIN card_groups cg ON cg.id = c.group_id WHERE uc.user_id = ? AND c.group_id = ? ORDER BY c.id LIMIT ? OFFSET ?`, [userId, group_id, parseInt(limit), parseInt(offset)] ); const [[{ total }]] = await db.query( `SELECT COUNT(*) AS total FROM user_cards uc JOIN cards c ON c.id = uc.card_id WHERE uc.user_id = ? AND c.group_id = ?`, [userId, group_id] ); res.json({ cards, total, page: parseInt(page), totalPages: Math.ceil(total / limit) }); } catch (err) { console.error(err); res.status(500).json({ error: "DB Fehler" }); } }); /* ════════════════════════════════════════════ GET /api/decks Alle Decks des Spielers ════════════════════════════════════════════ */ router.get("/decks", async (req, res) => { const userId = req.session.user.id; try { const [decks] = await db.query( `SELECT d.id, d.name, COALESCE(SUM(dc.amount), 0) AS card_count FROM decks d LEFT JOIN deck_cards dc ON dc.deck_id = d.id WHERE d.user_id = ? GROUP BY d.id ORDER BY d.created_at`, [userId] ); res.json(decks); } catch (err) { console.error(err); res.status(500).json({ error: "DB Fehler" }); } }); /* ════════════════════════════════════════════ POST /api/decks { name } Neues Deck erstellen (max. 10 pro Spieler) ════════════════════════════════════════════ */ router.post("/decks", async (req, res) => { const userId = req.session.user.id; const { name } = req.body; if (!name || !name.trim()) { return res.status(400).json({ error: "Name darf nicht leer sein." }); } try { const [[{ count }]] = await db.query( "SELECT COUNT(*) AS count FROM decks WHERE user_id = ?", [userId] ); if (count >= 10) { return res.status(400).json({ error: "Maximale Anzahl von 10 Decks erreicht." }); } const [result] = await db.query( "INSERT INTO decks (user_id, name) VALUES (?, ?)", [userId, name.trim()] ); res.status(201).json({ id: result.insertId, name: name.trim(), card_count: 0 }); } catch (err) { console.error(err); res.status(500).json({ error: "DB Fehler" }); } }); /* ════════════════════════════════════════════ GET /api/decks/:id/cards Karten eines bestimmten Decks ════════════════════════════════════════════ */ router.get("/decks/:id/cards", async (req, res) => { const userId = req.session.user.id; const deckId = req.params.id; try { // Deck gehört dem Spieler? const [[deck]] = await db.query( "SELECT id FROM decks WHERE id = ? AND user_id = ?", [deckId, userId] ); if (!deck) return res.status(404).json({ error: "Deck nicht gefunden." }); const [cards] = await db.query( `SELECT dc.card_id, LEAST(dc.amount, COALESCE(uc.amount, 0)) AS amount, c.name, c.image, c.rarity, c.attack, c.defends, c.cooldown, c.\`range\`, c.\`race\` FROM deck_cards dc JOIN cards c ON c.id = dc.card_id LEFT JOIN user_cards uc ON uc.card_id = dc.card_id AND uc.user_id = ? WHERE dc.deck_id = ? AND COALESCE(uc.amount, 0) > 0 ORDER BY c.name`, [userId, deckId] ); res.json(cards); } catch (err) { console.error(err); res.status(500).json({ error: "DB Fehler" }); } }); /* ════════════════════════════════════════════ POST /api/decks/:id/cards { card_id, level } Karte zum Deck hinzufügen ════════════════════════════════════════════ */ router.post("/decks/:id/cards", async (req, res) => { const userId = req.session.user.id; const deckId = req.params.id; const { card_id } = req.body; if (!card_id) return res.status(400).json({ error: "card_id fehlt." }); try { // Deck gehört dem Spieler? const [[deck]] = await db.query( "SELECT id FROM decks WHERE id = ? AND user_id = ?", [deckId, userId] ); if (!deck) return res.status(404).json({ error: "Deck nicht gefunden." }); // Besitzt der Spieler diese Karte? const [[owned]] = await db.query( "SELECT amount FROM user_cards WHERE user_id = ? AND card_id = ?", [userId, card_id] ); if (!owned) return res.status(400).json({ error: "Du besitzt diese Karte nicht." }); // Deck-Gesamtzahl prüfen (max 30) const [[{ total }]] = await db.query( "SELECT COALESCE(SUM(amount), 0) AS total FROM deck_cards WHERE deck_id = ?", [deckId] ); if (total >= 30) { return res.status(400).json({ error: "Deck ist voll (max. 30 Karten)." }); } // Rarity > 5: max. 1× im Deck const [[cardInfo]] = await db.query( "SELECT rarity FROM cards WHERE id = ?", [card_id] ); const [[existing]] = await db.query( "SELECT amount FROM deck_cards WHERE deck_id = ? AND card_id = ?", [deckId, card_id] ); if (parseInt(cardInfo?.rarity) > 5 && existing) { return res.status(400).json({ error: "Karten ab Rarity 6 dürfen nur einmal im Deck sein." }); } // Nicht mehr einfügen als besessen const currentInDeck = existing ? existing.amount : 0; if (currentInDeck >= owned.amount) { return res.status(400).json({ error: "Du hast keine weiteren Exemplare dieser Karte." }); } // Einfügen oder erhöhen if (existing) { await db.query( "UPDATE deck_cards SET amount = amount + 1 WHERE deck_id = ? AND card_id = ?", [deckId, card_id] ); } else { await db.query( "INSERT INTO deck_cards (deck_id, card_id, amount) VALUES (?, ?, 1)", [deckId, card_id] ); } res.json({ success: true }); } catch (err) { // DB-Trigger Fehler (45000) sauber weitergeben if (err.sqlState === "45000") { return res.status(400).json({ error: err.message }); } console.error(err); res.status(500).json({ error: "DB Fehler" }); } }); /* ════════════════════════════════════════════ DELETE /api/decks/:id/cards { card_id, level } Karte aus Deck entfernen (amount - 1, bei 0 löschen) ════════════════════════════════════════════ */ router.delete("/decks/:id/cards", async (req, res) => { const userId = req.session.user.id; const deckId = req.params.id; const { card_id } = req.body; if (!card_id) return res.status(400).json({ error: "card_id fehlt." }); try { // Deck gehört dem Spieler? const [[deck]] = await db.query( "SELECT id FROM decks WHERE id = ? AND user_id = ?", [deckId, userId] ); if (!deck) return res.status(404).json({ error: "Deck nicht gefunden." }); const [[entry]] = await db.query( "SELECT id, amount FROM deck_cards WHERE deck_id = ? AND card_id = ?", [deckId, card_id] ); if (!entry) return res.status(404).json({ error: "Karte nicht im Deck." }); if (entry.amount > 1) { await db.query( "UPDATE deck_cards SET amount = amount - 1 WHERE id = ?", [entry.id] ); } else { await db.query("DELETE FROM deck_cards WHERE id = ?", [entry.id]); } res.json({ success: true }); } catch (err) { console.error(err); res.status(500).json({ error: "DB Fehler" }); } }); module.exports = router;