import { sql } from '../../../lib/sql.js'; import { getUserFromRequest } from '../../../lib/permission-middleware'; import { isValidSlug } from '../../../lib/slug-utils'; export default async function handler(req, res) { try { // Try to get authenticated user (optional for public collections) const user = await getUserFromRequest(req); 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)); // Build the query based on identifier type let collectionQuery; if (isSlug) { collectionQuery = sql` SELECT DISTINCT c.*, u.email as creator_email, COUNT(cc.card_id) as card_count, COALESCE(SUM(cards.market_price * cc.quantity), 0) as total_value, ${user ? sql`cp.role as user_role, CASE WHEN c.user_id = ${user.userId} THEN 'owner' WHEN cp.role IS NOT NULL THEN cp.role ELSE NULL END as effective_role` : sql`NULL as user_role, NULL as effective_role`} FROM collections c LEFT JOIN users u ON c.user_id = u.id LEFT JOIN collection_cards cc ON c.id = cc.collection_id LEFT JOIN cards ON cc.card_id = cards.id LEFT JOIN collection_permissions cp ON c.id = cp.collection_id AND cp.user_id = ${user ? user.userId : null} AND cp.status = 'active' WHERE c.slug = ${identifier} AND ( c.user_id = ${user ? user.userId : null} OR cp.id IS NOT NULL OR c.is_public = true ) GROUP BY c.id, u.email, cp.role `; } else { const numericId = parseInt(identifier); collectionQuery = sql` SELECT DISTINCT c.*, u.email as creator_email, COUNT(cc.card_id) as card_count, COALESCE(SUM(cards.market_price * cc.quantity), 0) as total_value, ${user ? sql`cp.role as user_role, CASE WHEN c.user_id = ${user.userId} THEN 'owner' WHEN cp.role IS NOT NULL THEN cp.role ELSE NULL END as effective_role` : sql`NULL as user_role, NULL as effective_role`} FROM collections c LEFT JOIN users u ON c.user_id = u.id LEFT JOIN collection_cards cc ON c.id = cc.collection_id LEFT JOIN cards ON cc.card_id = cards.id LEFT JOIN collection_permissions cp ON c.id = cp.collection_id AND cp.user_id = ${user ? user.userId : null} AND cp.status = 'active' WHERE c.id = ${numericId} AND ( c.user_id = ${user ? user.userId : null} OR cp.id IS NOT NULL OR c.is_public = true ) GROUP BY c.id, u.email, cp.role `; } const collectionResult = await collectionQuery; 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') { const formattedCollection = { id: collection.id, slug: collection.slug, name: collection.name, description: collection.description, tcg: collection.tcg || 'MTG', cardCount: parseInt(collection.card_count) || 0, value: parseFloat(collection.total_value) || 0, lastViewed: collection.updated_at, createdAt: collection.created_at, isPublic: collection.is_public || false, isSystemCollection: collection.is_system_collection || false, image: collection.image, tags: collection.tags ? collection.tags.split(',') : [], creator: collection.creator_email, userRole: collection.effective_role }; res.status(200).json(formattedCollection); } else if (req.method === 'PUT') { // Only allow updates by owner if (collection.user_id !== user?.userId) { return res.status(403).json({ error: 'Only collection owners can edit collections' }); } const { name, description, isPublic, image, tags } = req.body; // Prevent system collections from being made public if (collection.is_system_collection && isPublic === true) { return res.status(403).json({ error: 'System collections cannot be made public' }); } // Prevent renaming system collections if (collection.is_system_collection && name !== undefined && name !== collection.name) { return res.status(403).json({ error: 'System collections cannot be renamed' }); } // If name is being changed, generate new slug let updateFields = []; let updateValues = []; let paramIndex = 1; if (name !== undefined && name !== collection.name) { // Generate new unique slug if name changed const existingSlugsResult = await sql`SELECT slug FROM collections WHERE slug IS NOT NULL AND id != ${collection.id}`; const existingSlugs = existingSlugsResult.rows.map(row => row.slug); const { generateUniqueSlug } = await import('../../../lib/slug-utils'); const newSlug = await generateUniqueSlug(name, existingSlugs); updateFields.push(`name = $${paramIndex}`, `slug = $${paramIndex + 1}`); updateValues.push(name, newSlug); paramIndex += 2; } if (description !== undefined) { updateFields.push(`description = $${paramIndex}`); updateValues.push(description); paramIndex++; } if (isPublic !== undefined) { updateFields.push(`is_public = $${paramIndex}`); updateValues.push(isPublic); paramIndex++; } if (image !== undefined) { updateFields.push(`image = $${paramIndex}`); updateValues.push(image); paramIndex++; } if (tags !== undefined) { updateFields.push(`tags = $${paramIndex}`); updateValues.push(Array.isArray(tags) ? tags.join(',') : tags); paramIndex++; } if (updateFields.length === 0) { return res.status(400).json({ error: 'No fields to update' }); } updateFields.push('updated_at = CURRENT_TIMESTAMP'); updateValues.push(collection.id); const updateQuery = ` UPDATE collections SET ${updateFields.join(', ')} WHERE id = $${paramIndex} RETURNING * `; const updateResult = await sql.query(updateQuery, updateValues); const updatedCollection = { id: updateResult.rows[0].id, slug: updateResult.rows[0].slug, name: updateResult.rows[0].name, description: updateResult.rows[0].description, isPublic: updateResult.rows[0].is_public, isSystemCollection: updateResult.rows[0].is_system_collection, image: updateResult.rows[0].image, tags: updateResult.rows[0].tags ? updateResult.rows[0].tags.split(',') : [] }; res.status(200).json(updatedCollection); } else if (req.method === 'DELETE') { // Only allow deletion by owner if (collection.user_id !== user?.userId) { return res.status(403).json({ error: 'Only collection owners can delete collections' }); } // Prevent deletion of system collections if (collection.is_system_collection) { return res.status(403).json({ error: 'System collections cannot be deleted' }); } // Delete collection and all related data await sql`DELETE FROM collection_cards WHERE collection_id = ${collection.id}`; await sql`DELETE FROM collection_permissions WHERE collection_id = ${collection.id}`; await sql`DELETE FROM collections WHERE id = ${collection.id}`; res.status(200).json({ message: 'Collection deleted successfully' }); } else { res.status(405).json({ error: 'Method not allowed' }); } } catch (error) { console.error('Collection API error:', error); res.status(500).json({ error: 'Internal server error' }); } }