import { sql } from '../../../lib/sql.js'; import { getUserFromRequest } from '../../../lib/permission-middleware'; export default async function handler(req, res) { try { const user = await getUserFromRequest(req); if (!user) { return res.status(401).json({ error: 'Authentication required' }); } const gameId = parseInt(req.query.id, 10); if (!Number.isInteger(gameId)) { return res.status(400).json({ error: 'Invalid game id' }); } const found = await sql` SELECT * FROM custom_games WHERE id = ${gameId} AND user_id = ${user.userId} `; if (found.rows.length === 0) { return res.status(404).json({ error: 'Game not found' }); } const game = found.rows[0]; if (req.method === 'GET') { const cards = await sql` SELECT c.id, c.card_id, c.name, c.mana_cost, c.card_type, c.rarity, c.rules_text, c.actions, c.flavor_quote, c.power, c.toughness, c.frame_id, c.artwork_url, c.art_mode, f.id AS frame_pk, f.name AS frame_name, f.palette AS frame_palette, f.texture_url AS frame_texture, f.frame_image_url AS frame_image, f.layout AS frame_layout, c.created_at, c.updated_at FROM custom_cards c LEFT JOIN custom_frames f ON f.id = c.custom_frame_id WHERE c.custom_game_id = ${gameId} ORDER BY c.updated_at DESC `; const designs = cards.rows.map((row) => { const { frame_pk, frame_name, frame_palette, frame_texture, frame_image, frame_layout, ...rest } = row; return { ...rest, custom_frame: frame_pk != null ? { id: frame_pk, name: frame_name, palette: frame_palette, texture_url: frame_texture, frame_image_url: frame_image, layout: frame_layout, } : null, }; }); return res.status(200).json({ game, designs }); } if (req.method === 'PUT') { const name = typeof req.body?.name === 'string' ? req.body.name.trim() : ''; const description = typeof req.body?.description === 'string' ? req.body.description.trim() : null; const isPublic = typeof req.body?.is_public === 'boolean' ? req.body.is_public : game.is_public; if (!name) { return res.status(400).json({ error: 'Game name is required' }); } const clash = await sql` SELECT id FROM custom_games WHERE user_id = ${user.userId} AND lower(name) = ${name.toLowerCase()} AND id <> ${gameId} `; if (clash.rows.length > 0) { return res.status(409).json({ error: 'You already have a game with that name' }); } const updated = await sql` UPDATE custom_games SET name = ${name}, description = ${description}, is_public = ${isPublic}, updated_at = CURRENT_TIMESTAMP WHERE id = ${gameId} RETURNING * `; return res.status(200).json({ game: updated.rows[0] }); } if (req.method === 'DELETE') { // Designs keep existing (custom_game_id drops to NULL via FK); // their catalog twins stay in the collection untouched. await sql`DELETE FROM custom_games WHERE id = ${gameId}`; return res.status(200).json({ message: 'Game deleted' }); } return res.status(405).json({ error: 'Method not allowed' }); } catch (error) { console.error('Custom game API error:', error); return res.status(500).json({ error: 'Internal server error' }); } }