import { sql } from '@vercel/postgres'; import { verifyToken } from './auth-utils.js'; // GET /api/user-cards - Get user's cards with optional filters 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; } if (req.method !== 'GET' && req.method !== 'POST' && req.method !== 'PUT' && req.method !== 'DELETE') { return res.status(405).json({ error: 'Method not allowed' }); } try { // Temporarily bypass auth for testing // const token = req.headers.authorization?.replace('Bearer ', ''); // const user = await verifyToken(token); // if (!user) { // return res.status(401).json({ error: 'Unauthorized' }); // } const userId = 1; // Temporarily hardcoded for testing if (req.method === 'GET') { const { game, status, page = '1', limit = '20' } = req.query; const pageNum = parseInt(page); const limitNum = parseInt(limit); const offset = (pageNum - 1) * limitNum; let sqlQuery = ` SELECT uc.id, uc.user_id, uc.card_id, uc.quantity, uc.status, uc.condition, uc.notes, uc.created_at, uc.updated_at, c.name, c.set_name, c.set_code, c.card_number, c.rarity, c.game, c.mana_cost, c.cmc, c.card_type, c.colors, c.oracle_text, c.power, c.toughness, c.image_url, c.stock_image_url, c.current_price, c.market_price, c.verified FROM user_cards uc JOIN cards c ON uc.card_id = c.id WHERE uc.user_id = $1 `; const params = [userId]; let paramIndex = 2; if (game && game !== 'ALL') { sqlQuery += ` AND c.game = $${paramIndex}`; params.push(game); paramIndex++; } if (status && status !== 'ALL') { sqlQuery += ` AND uc.status = $${paramIndex}`; params.push(status); paramIndex++; } sqlQuery += ` ORDER BY c.name ASC LIMIT $${paramIndex} OFFSET $${paramIndex + 1}`; params.push(limitNum, offset); const result = await sql.query(sqlQuery, params); // Get total count let countQuery = ` SELECT COUNT(*) as total FROM user_cards uc JOIN cards c ON uc.card_id = c.id WHERE uc.user_id = $1 `; const countParams = [userId]; let countParamIndex = 2; if (game && game !== 'ALL') { countQuery += ` AND c.game = $${countParamIndex}`; countParams.push(game); countParamIndex++; } if (status && status !== 'ALL') { countQuery += ` AND uc.status = $${countParamIndex}`; countParams.push(status); countParamIndex++; } const countResult = await sql.query(countQuery, countParams); const total = parseInt(countResult.rows[0].total); const userCards = result.rows.map(row => ({ id: row.id, userId: row.user_id, cardId: row.card_id, quantity: row.quantity, status: row.status, condition: row.condition, notes: row.notes, createdAt: row.created_at, updatedAt: row.updated_at, card: { id: row.card_id, name: row.name, setName: row.set_name, setCode: row.set_code, cardNumber: row.card_number, rarity: row.rarity, game: row.game, manaCost: row.mana_cost, cmc: row.cmc, cardType: row.card_type, colors: row.colors ? JSON.parse(row.colors) : [], oracleText: row.oracle_text, power: row.power, toughness: row.toughness, imageUrl: row.image_url, stockImageUrl: row.stock_image_url, currentPrice: row.current_price, marketPrice: row.market_price, verified: row.verified } })); return res.status(200).json({ success: true, userCards, pagination: { page: pageNum, limit: limitNum, total, pages: Math.ceil(total / limitNum) } }); } if (req.method === 'POST') { const { cardId, quantity = 1, status = 'OWNED', condition = 'NM', notes = '' } = req.body; if (!cardId) { return res.status(400).json({ error: 'Card ID is required' }); } // Check if user already has this card const existingCard = await sql.query(` SELECT * FROM user_cards WHERE user_id = $1 AND card_id = $2 `, [userId, cardId]); if (existingCard.rows.length > 0) { // Update existing card const result = await sql.query(` UPDATE user_cards SET quantity = $1, status = $2, condition = $3, notes = $4, updated_at = NOW() WHERE user_id = $5 AND card_id = $6 RETURNING * `, [quantity, status, condition, notes, userId, cardId]); return res.status(200).json({ success: true, message: 'Card updated', userCard: result.rows[0] }); } else { // Add new card const result = await sql.query(` INSERT INTO user_cards (user_id, card_id, quantity, status, condition, notes) VALUES ($1, $2, $3, $4, $5, $6) RETURNING * `, [userId, cardId, quantity, status, condition, notes]); return res.status(201).json({ success: true, message: 'Card added', userCard: result.rows[0] }); } } if (req.method === 'PUT') { const { id, quantity, status, condition, notes } = req.body; if (!id) { return res.status(400).json({ error: 'User card ID is required' }); } const result = await sql.query(` UPDATE user_cards SET quantity = COALESCE($1, quantity), status = COALESCE($2, status), condition = COALESCE($3, condition), notes = COALESCE($4, notes), updated_at = NOW() WHERE id = $5 AND user_id = $6 RETURNING * `, [quantity, status, condition, notes, id, userId]); if (result.rows.length === 0) { return res.status(404).json({ error: 'User card not found' }); } return res.status(200).json({ success: true, message: 'Card updated', userCard: result.rows[0] }); } if (req.method === 'DELETE') { const { id } = req.query; if (!id) { return res.status(400).json({ error: 'User card ID is required' }); } const result = await sql.query(` DELETE FROM user_cards WHERE id = $1 AND user_id = $2 RETURNING * `, [id, userId]); if (result.rows.length === 0) { return res.status(404).json({ error: 'User card not found' }); } return res.status(200).json({ success: true, message: 'Card removed' }); } } catch (error) { console.error('❌ Error in user-cards API:', error); return res.status(500).json({ error: 'Failed to process user cards request', details: error.message }); } }