import { NextResponse } from 'next/server'; import { sql } from '@vercel/postgres'; import { verifyToken } from './setup-auth.js'; // GET /api/user-cards - Get user's cards with optional filters export async function GET(request) { try { const token = request.headers.get('authorization')?.replace('Bearer ', ''); const user = await verifyToken(token); if (!user) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } // Check if tables exist first try { const tableCheck = await sql.query(` SELECT EXISTS ( SELECT FROM information_schema.tables WHERE table_name = 'user_cards' ) as user_cards_exists, EXISTS ( SELECT FROM information_schema.tables WHERE table_name = 'cards' ) as cards_exists `); const { user_cards_exists, cards_exists } = tableCheck.rows[0]; if (!user_cards_exists || !cards_exists) { console.log('Tables do not exist, returning empty array'); return NextResponse.json({ success: true, data: [], message: 'No cards found (tables not initialized)' }); } } catch (error) { console.error('Error checking table existence:', error); return NextResponse.json({ success: true, data: [], message: 'Database not initialized' }); } const { searchParams } = new URL(request.url); const game = searchParams.get('game'); const rarity = searchParams.get('rarity'); const status = searchParams.get('status'); const search = searchParams.get('search'); let query = ` SELECT uc.id, uc.user_id, uc.card_id, uc.status, uc.quantity, uc.condition, uc.notes, uc.acquired_date, uc.acquired_price, uc.acquired_from, uc.created_at, uc.updated_at, c.name, c.set_name, c.set_code, c.card_number, c.rarity, c.game, c.card_type, c.mana_cost, c.cmc, c.colors, c.oracle_text, c.power, c.toughness, c.image_url, c.stock_image_url, c.current_price, c.market_price, c.verified, c.created_at as card_created_at, c.updated_at as card_updated_at FROM user_cards uc JOIN cards c ON uc.card_id = c.id WHERE uc.user_id = $1 `; const params = [user.id]; let paramIndex = 2; if (game) { query += ` AND c.game = $${paramIndex}`; params.push(game); paramIndex++; } if (rarity) { query += ` AND c.rarity = $${paramIndex}`; params.push(rarity); paramIndex++; } if (status && status !== 'all') { query += ` AND uc.status = $${paramIndex}`; params.push(status); paramIndex++; } if (search) { query += ` AND (c.name ILIKE $${paramIndex} OR c.set_name ILIKE $${paramIndex})`; params.push(`%${search}%`); paramIndex++; } query += ` ORDER BY uc.created_at DESC`; const result = await sql.query(query, params); const userCards = result.rows.map(row => ({ id: row.id, userId: row.user_id, cardId: row.card_id, status: row.status, quantity: row.quantity, condition: row.condition, notes: row.notes, acquiredDate: row.acquired_date, acquiredPrice: row.acquired_price, acquiredFrom: row.acquired_from, createdAt: row.created_at, updatedAt: row.updated_at, card: { id: row.card_id, name: row.name, set_name: row.set_name, set_code: row.set_code, card_number: row.card_number, rarity: row.rarity, game: row.game, card_type: row.card_type, mana_cost: row.mana_cost, cmc: row.cmc, colors: row.colors ? JSON.parse(row.colors) : [], oracle_text: row.oracle_text, power: row.power, toughness: row.toughness, image_url: row.image_url, stock_image_url: row.stock_image_url, current_price: row.current_price, market_price: row.market_price, verified: row.verified, createdAt: row.card_created_at, updatedAt: row.card_updated_at, } })); return NextResponse.json({ success: true, data: userCards, message: `Found ${userCards.length} cards` }); } catch (error) { console.error('Error fetching user cards:', error); return NextResponse.json( { error: 'Failed to fetch user cards' }, { status: 500 } ); } } // POST /api/user-cards - Add card to user collection export async function POST(request) { try { const token = request.headers.get('authorization')?.replace('Bearer ', ''); const user = await verifyToken(token); if (!user) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const body = await request.json(); const { cardId, status = 'owned', quantity = 1, condition, notes, acquiredDate, acquiredPrice, acquiredFrom, collectionIds = [], deckIds = [] } = body; if (!cardId) { return NextResponse.json( { error: 'Card ID is required' }, { status: 400 } ); } // Check if card exists const cardResult = await sql.query( 'SELECT id FROM cards WHERE id = $1', [cardId] ); if (cardResult.rows.length === 0) { return NextResponse.json( { error: 'Card not found' }, { status: 404 } ); } // Check if user already has this card const existingResult = await sql.query( 'SELECT id FROM user_cards WHERE user_id = $1 AND card_id = $2', [user.id, cardId] ); if (existingResult.rows.length > 0) { return NextResponse.json( { error: 'Card already in collection' }, { status: 409 } ); } // Add card to user collection const result = await sql.query( `INSERT INTO user_cards ( user_id, card_id, status, quantity, condition, notes, acquired_date, acquired_price, acquired_from, created_at, updated_at ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, NOW(), NOW()) RETURNING *`, [ user.id, cardId, status, quantity, condition, notes, acquiredDate, acquiredPrice, acquiredFrom ] ); const userCard = result.rows[0]; // Add to collections if specified if (collectionIds.length > 0) { for (const collectionId of collectionIds) { await sql.query( 'INSERT INTO collection_cards (collection_id, user_card_id) VALUES ($1, $2)', [collectionId, userCard.id] ); } } // Add to decks if specified if (deckIds.length > 0) { for (const deckId of deckIds) { await sql.query( 'INSERT INTO deck_cards (deck_id, user_card_id, quantity, board) VALUES ($1, $2, $3, $4)', [deckId, userCard.id, quantity, 'mainboard'] ); } } return NextResponse.json({ success: true, data: { id: userCard.id, userId: userCard.user_id, cardId: userCard.card_id, status: userCard.status, quantity: userCard.quantity, condition: userCard.condition, notes: userCard.notes, acquiredDate: userCard.acquired_date, acquiredPrice: userCard.acquired_price, acquiredFrom: userCard.acquired_from, createdAt: userCard.created_at, updatedAt: userCard.updated_at, }, message: 'Card added to collection' }); } catch (error) { console.error('Error adding card to collection:', error); return NextResponse.json( { error: 'Failed to add card to collection' }, { status: 500 } ); } } // PUT /api/user-cards/[id] - Update user card export async function PUT(request, { params }) { try { const token = request.headers.get('authorization')?.replace('Bearer ', ''); const user = await verifyToken(token); if (!user) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const { id } = params; const body = await request.json(); // Check if user owns this card const ownershipResult = await sql.query( 'SELECT id FROM user_cards WHERE id = $1 AND user_id = $2', [id, user.id] ); if (ownershipResult.rows.length === 0) { return NextResponse.json( { error: 'Card not found or not owned by user' }, { status: 404 } ); } // Build update query dynamically const updateFields = []; const updateValues = []; let paramIndex = 1; if (body.status !== undefined) { updateFields.push(`status = $${paramIndex}`); updateValues.push(body.status); paramIndex++; } if (body.quantity !== undefined) { updateFields.push(`quantity = $${paramIndex}`); updateValues.push(body.quantity); paramIndex++; } if (body.condition !== undefined) { updateFields.push(`condition = $${paramIndex}`); updateValues.push(body.condition); paramIndex++; } if (body.notes !== undefined) { updateFields.push(`notes = $${paramIndex}`); updateValues.push(body.notes); paramIndex++; } if (body.acquiredDate !== undefined) { updateFields.push(`acquired_date = $${paramIndex}`); updateValues.push(body.acquiredDate); paramIndex++; } if (body.acquiredPrice !== undefined) { updateFields.push(`acquired_price = $${paramIndex}`); updateValues.push(body.acquiredPrice); paramIndex++; } if (body.acquiredFrom !== undefined) { updateFields.push(`acquired_from = $${paramIndex}`); updateValues.push(body.acquiredFrom); paramIndex++; } if (updateFields.length === 0) { return NextResponse.json( { error: 'No fields to update' }, { status: 400 } ); } updateFields.push(`updated_at = NOW()`); updateValues.push(id); const query = ` UPDATE user_cards SET ${updateFields.join(', ')} WHERE id = $${paramIndex} RETURNING * `; const result = await sql.query(query, updateValues); const userCard = result.rows[0]; return NextResponse.json({ success: true, data: { id: userCard.id, userId: userCard.user_id, cardId: userCard.card_id, status: userCard.status, quantity: userCard.quantity, condition: userCard.condition, notes: userCard.notes, acquiredDate: userCard.acquired_date, acquiredPrice: userCard.acquired_price, acquiredFrom: userCard.acquired_from, createdAt: userCard.created_at, updatedAt: userCard.updated_at, }, message: 'Card updated successfully' }); } catch (error) { console.error('Error updating user card:', error); return NextResponse.json( { error: 'Failed to update card' }, { status: 500 } ); } } // DELETE /api/user-cards/[id] - Delete user card export async function DELETE(request, { params }) { try { const token = request.headers.get('authorization')?.replace('Bearer ', ''); const user = await verifyToken(token); if (!user) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const { id } = params; // Check if user owns this card const ownershipResult = await sql.query( 'SELECT id FROM user_cards WHERE id = $1 AND user_id = $2', [id, user.id] ); if (ownershipResult.rows.length === 0) { return NextResponse.json( { error: 'Card not found or not owned by user' }, { status: 404 } ); } // Delete from collections and decks first await sql.query('DELETE FROM collection_cards WHERE user_card_id = $1', [id]); await sql.query('DELETE FROM deck_cards WHERE user_card_id = $1', [id]); // Delete the user card await sql.query('DELETE FROM user_cards WHERE id = $1', [id]); return NextResponse.json({ success: true, message: 'Card removed from collection' }); } catch (error) { console.error('Error deleting user card:', error); return NextResponse.json( { error: 'Failed to delete card' }, { status: 500 } ); } }