import { type NextRequest, NextResponse } from 'next/server'; import { withAuth } from '@/lib/apiHelpers'; import pool from '@/lib/db'; interface CircuitNetwork { green: Record; red: Record; } interface IngestBody { game_tick: number; circuit_network: CircuitNetwork; logistic_network: Record; } export const POST = withAuth(async (req: NextRequest, { params }) => { const { combinator } = await params; const mtimeHeader = req.headers.get('x-file-mtime'); const realTime = mtimeHeader ? new Date(parseInt(mtimeHeader, 10)) : new Date(); let body: IngestBody; try { body = await req.json(); } catch { return NextResponse.json({ error: 'Invalid JSON' }, { status: 400 }); } const { game_tick, circuit_network, logistic_network } = body; if (typeof game_tick !== 'number') { return NextResponse.json({ error: 'Missing game_tick' }, { status: 400 }); } const green = circuit_network?.green ?? {}; const red = circuit_network?.red ?? {}; const logistic = logistic_network ?? {}; const allKeys = new Set([...Object.keys(green), ...Object.keys(red), ...Object.keys(logistic)]); if (allKeys.size === 0) return NextResponse.json({ ok: true, rows: 0 }); const client = await pool.connect(); try { await client.query('BEGIN'); const values: unknown[] = []; const placeholders: string[] = []; let idx = 1; for (const key of allKeys) { placeholders.push(`($${idx++},$${idx++},$${idx++},$${idx++},$${idx++},$${idx++},$${idx++})`); values.push( realTime, game_tick, combinator, key, green[key] ?? 0, red[key] ?? 0, logistic[key] ?? null, ); } await client.query( `INSERT INTO signals (real_time, game_tick, combinator, item_key, green, red, logistic) VALUES ${placeholders.join(', ')}`, values, ); await client.query( `INSERT INTO tick_timing (real_time, game_tick, combinator) VALUES ($1,$2,$3)`, [realTime, game_tick, combinator], ); await client.query('COMMIT'); return NextResponse.json({ ok: true, rows: allKeys.size }); } catch (err) { await client.query('ROLLBACK'); throw err; // re-throw — withAuth handler catches and returns 500 } finally { client.release(); } });