import { NextRequest, NextResponse } from 'next/server'; import { Pool } from 'pg'; import cardsData from '../src/data/cards.json'; // Create PostgreSQL connection pool const pool = new Pool({ connectionString: process.env.DATABASE_URL, ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false, }); interface JsonCard { id: number; name: string; set_name?: string; set_code?: string; card_number?: string; rarity?: string; game: string; mana_cost?: string; cmc?: number; card_type?: string; colors?: string[] | null; oracle_text?: string; flavor_text?: string | null; power?: string | null; toughness?: string | null; loyalty?: string | null; artist?: string | null; image_url?: string; stock_image_url?: string; artwork_crop_coords?: any; current_price?: number; market_price?: number; low_price?: number | null; high_price?: number | null; price_last_updated?: string | null; ocr_confidence?: number | null; ocr_raw_text?: string | null; scryfall_id?: string | null; tcg_player_id?: string | null; verified: number; // JSON has number, but we want boolean created_at?: string; updated_at?: string; } export default async function handler(req: NextRequest) { // Only allow POST requests for security if (req.method !== 'POST') { return new NextResponse(JSON.stringify({ error: 'Method not allowed' }), { status: 405, headers: { 'Content-Type': 'application/json' }, }); } const client = await pool.connect(); try { console.log('Starting card migration to Neon database...'); // Check if cards already exist to prevent duplicate migration const existingCards = await client.query('SELECT COUNT(*) as count FROM cards'); const cardCount = existingCards.rows[0]?.count || 0; if (cardCount > 0) { return new NextResponse(JSON.stringify({ message: `Database already contains ${cardCount} cards. Migration skipped.`, cards_count: cardCount }), { status: 200, headers: { 'Content-Type': 'application/json' }, }); } // Migrate cards from JSON const cards = cardsData as JsonCard[]; console.log(`Migrating ${cards.length} cards...`); let migratedCount = 0; const errors: string[] = []; for (const card of cards) { try { await client.query(` INSERT INTO cards ( name, set_name, set_code, card_number, rarity, game, mana_cost, cmc, card_type, colors, oracle_text, flavor_text, power, toughness, loyalty, artist, image_url, stock_image_url, artwork_crop_coords, current_price, market_price, low_price, high_price, price_last_updated, ocr_confidence, ocr_raw_text, scryfall_id, tcg_player_id, verified, created_at, updated_at ) VALUES ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31 ) `, [ card.name, card.set_name || null, card.set_code || null, card.card_number || null, card.rarity || null, card.game, card.mana_cost || null, card.cmc || null, card.card_type || null, card.colors ? JSON.stringify(card.colors) : null, card.oracle_text || null, card.flavor_text || null, card.power || null, card.toughness || null, card.loyalty || null, card.artist || null, card.image_url || null, card.stock_image_url || null, card.artwork_crop_coords ? JSON.stringify(card.artwork_crop_coords) : null, card.current_price || null, card.market_price || null, card.low_price || null, card.high_price || null, card.price_last_updated ? new Date(card.price_last_updated) : null, card.ocr_confidence || null, card.ocr_raw_text || null, card.scryfall_id || null, card.tcg_player_id || null, Boolean(card.verified), card.created_at ? new Date(card.created_at) : new Date(), card.updated_at ? new Date(card.updated_at) : new Date() ]); migratedCount++; } catch (error) { const errorMsg = `Error migrating card ${card.name}: ${(error as Error).message}`; console.error(errorMsg); errors.push(errorMsg); } } // Get final count to verify const finalCount = await client.query('SELECT COUNT(*) as count FROM cards'); const finalCardCount = finalCount.rows[0]?.count || 0; console.log(`✅ Successfully migrated ${migratedCount} cards to Neon database!`); return new NextResponse(JSON.stringify({ success: true, message: `Successfully migrated ${migratedCount} out of ${cards.length} cards`, cards_migrated: migratedCount, total_cards_in_db: finalCardCount, errors: errors.length > 0 ? errors : undefined }), { status: 200, headers: { 'Content-Type': 'application/json' }, }); } catch (error) { console.error('Migration failed:', error); return new NextResponse(JSON.stringify({ success: false, error: 'Migration failed', details: (error as Error).message }), { status: 500, headers: { 'Content-Type': 'application/json' }, }); } finally { client.release(); } }