import { NextRequest, NextResponse } from 'next/server'; import { neon } from '@neondatabase/serverless'; import cardsData from '../src/data/cards.json'; // Initialize Neon client const sql = neon(process.env.DATABASE_URL!); 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' }, }); } try { console.log('Starting card migration to Neon database...'); // Check if cards already exist to prevent duplicate migration const existingCards = await sql`SELECT COUNT(*) as count FROM cards`; const cardCount = existingCards[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 sql` 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 ( ${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.message}`; console.error(errorMsg); errors.push(errorMsg); } } // Get final count to verify const finalCount = await sql`SELECT COUNT(*) as count FROM cards`; const finalCardCount = finalCount[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.message }), { status: 500, headers: { 'Content-Type': 'application/json' }, }); } }