import { sql } from '@vercel/postgres'; import { getUserFromRequest } from '../../../../lib/permission-middleware'; import { isValidSlug } from '../../../../lib/slug-utils'; export default async function handler(req, res) { // Set CORS headers res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); // Handle preflight requests if (req.method === 'OPTIONS') { res.status(200).end(); return; } try { // Get authenticated user const user = await getUserFromRequest(req); if (!user) { return res.status(401).json({ error: 'Authentication required' }); } const { identifier } = req.query; if (!identifier) { return res.status(400).json({ error: 'Collection identifier is required' }); } // Determine if identifier is a slug or numeric ID const isSlug = isValidSlug(identifier) || isNaN(parseInt(identifier)); // Get collection ID from identifier let collectionResult; if (isSlug) { collectionResult = await sql` SELECT c.*, cp.role as user_role FROM collections c LEFT JOIN collection_permissions cp ON c.id = cp.collection_id AND cp.user_id = ${user.userId} AND cp.status = 'active' WHERE c.slug = ${identifier} AND ( c.user_id = ${user.userId} OR cp.id IS NOT NULL OR c.is_public = true ) `; } else { const numericId = parseInt(identifier); collectionResult = await sql` SELECT c.*, cp.role as user_role FROM collections c LEFT JOIN collection_permissions cp ON c.id = cp.collection_id AND cp.user_id = ${user.userId} AND cp.status = 'active' WHERE c.id = ${numericId} AND ( c.user_id = ${user.userId} OR cp.id IS NOT NULL OR c.is_public = true ) `; } if (collectionResult.rows.length === 0) { return res.status(404).json({ error: 'Collection not found or access denied' }); } const collection = collectionResult.rows[0]; if (req.method === 'GET') { // Get all cards in the collection const cardsResult = await sql` SELECT cards.*, cc.quantity, cc.created_at as added_at FROM collection_cards cc JOIN cards ON cc.card_id = cards.id WHERE cc.collection_id = ${collection.id} ORDER BY cc.created_at DESC `; const cards = cardsResult.rows.map(card => ({ id: card.id, name: card.name, set_name: card.set_name, set_code: card.set_code, card_number: card.card_number, rarity: card.rarity, game: card.game, mana_cost: card.mana_cost, cmc: card.cmc, card_type: card.card_type, colors: card.colors, oracle_text: card.oracle_text, power: card.power, toughness: card.toughness, image_url: card.image_url, stock_image_url: card.stock_image_url, current_price: parseFloat(card.current_price) || 0, market_price: parseFloat(card.market_price) || 0, quantity: parseInt(card.quantity) || 1, added_at: card.added_at })); res.status(200).json({ cards }); } else if (req.method === 'POST') { // Add card to collection - only allow if user has write access const canWrite = collection.user_id === user.userId || ['owner', 'editor'].includes(collection.user_role); if (!canWrite) { return res.status(403).json({ error: 'You do not have permission to add cards to this collection' }); } const { cardId, quantity = 1 } = req.body; if (!cardId) { return res.status(400).json({ error: 'Card ID is required' }); } // Check if card exists const cardCheck = await sql`SELECT id FROM cards WHERE id = ${cardId}`; if (cardCheck.length === 0) { return res.status(404).json({ error: 'Card not found' }); } // Check if card already exists in collection const existingResult = await sql` SELECT * FROM collection_cards WHERE collection_id = ${collection.id} AND card_id = ${cardId} `; if (existingResult.length > 0) { // Update quantity if card already exists const result = await sql` UPDATE collection_cards SET quantity = quantity + ${quantity}, updated_at = CURRENT_TIMESTAMP WHERE collection_id = ${collection.id} AND card_id = ${cardId} RETURNING * `; res.status(200).json({ message: 'Card quantity updated in collection', card: result[0] }); } else { // Add new card to collection const result = await sql` INSERT INTO collection_cards (collection_id, card_id, quantity) VALUES (${collection.id}, ${cardId}, ${quantity}) RETURNING * `; res.status(201).json({ message: 'Card added to collection', card: result[0] }); } // Update collection's updated_at timestamp await sql` UPDATE collections SET updated_at = CURRENT_TIMESTAMP WHERE id = ${collection.id} `; } else if (req.method === 'PUT') { // Update card quantity in collection const canWrite = collection.user_id === user.userId || ['owner', 'editor'].includes(collection.user_role); if (!canWrite) { return res.status(403).json({ error: 'You do not have permission to modify this collection' }); } const { cardId, quantity } = req.body; if (!cardId || quantity === undefined) { return res.status(400).json({ error: 'Card ID and quantity are required' }); } if (quantity <= 0) { // Remove card from collection if quantity is 0 or negative await sql` DELETE FROM collection_cards WHERE collection_id = ${collection.id} AND card_id = ${cardId} `; res.status(200).json({ message: 'Card removed from collection' }); } else { // Update quantity const result = await sql` UPDATE collection_cards SET quantity = ${quantity}, updated_at = CURRENT_TIMESTAMP WHERE collection_id = ${collection.id} AND card_id = ${cardId} RETURNING * `; if (result.rows.length === 0) { return res.status(404).json({ error: 'Card not found in collection' }); } res.status(200).json({ message: 'Card quantity updated', card: result.rows[0] }); } // Update collection's updated_at timestamp await sql` UPDATE collections SET updated_at = CURRENT_TIMESTAMP WHERE id = ${collection.id} `; } else if (req.method === 'DELETE') { // Remove card from collection const canWrite = collection.user_id === user.userId || ['owner', 'editor'].includes(collection.user_role); if (!canWrite) { return res.status(403).json({ error: 'You do not have permission to modify this collection' }); } const { cardId } = req.body; if (!cardId) { return res.status(400).json({ error: 'Card ID is required' }); } const result = await sql` DELETE FROM collection_cards WHERE collection_id = ${collection.id} AND card_id = ${cardId} RETURNING * `; if (result.rows.length === 0) { return res.status(404).json({ error: 'Card not found in collection' }); } // Update collection's updated_at timestamp await sql` UPDATE collections SET updated_at = CURRENT_TIMESTAMP WHERE id = ${collection.id} `; res.status(200).json({ message: 'Card removed from collection' }); } else { res.status(405).json({ error: 'Method not allowed' }); } } catch (error) { console.error('Collection cards API error:', error); res.status(500).json({ error: 'Internal server error' }); } }