const express = require('express'); const router = express.Router(); // Get all import sessions for a user (named + unnamed) router.get('/', async (req, res) => { try { const { user_id } = req.query; if (!user_id) { return res.status(400).json({ error: 'user_id query parameter is required' }); } const pool = req.app.locals.pool; if (!pool) { throw new Error('Database pool not initialized'); } const result = await pool.query(` SELECT id, user_id, name, current_step, jsonb_array_length(data) as row_count, global_selections, created_at, updated_at FROM import_sessions WHERE user_id = $1 ORDER BY CASE WHEN name IS NULL THEN 0 ELSE 1 END, updated_at DESC `, [user_id]); res.json(result.rows); } catch (error) { console.error('Error fetching import sessions:', error); res.status(500).json({ error: 'Failed to fetch import sessions', details: error instanceof Error ? error.message : 'Unknown error' }); } }); // Get session by ID router.get('/:id', async (req, res) => { try { const { id } = req.params; const pool = req.app.locals.pool; if (!pool) { throw new Error('Database pool not initialized'); } const result = await pool.query(` SELECT * FROM import_sessions WHERE id = $1 `, [id]); if (result.rows.length === 0) { return res.status(404).json({ error: 'Import session not found' }); } res.json(result.rows[0]); } catch (error) { console.error('Error fetching import session:', error); res.status(500).json({ error: 'Failed to fetch import session', details: error instanceof Error ? error.message : 'Unknown error' }); } }); // Autosave - upsert unnamed session for user // IMPORTANT: This must be defined before /:id routes to avoid Express matching "autosave" as an :id router.put('/autosave', async (req, res) => { try { const { user_id, current_step, data, product_images, global_selections, validation_state } = req.body; // Validate required fields if (!user_id) { return res.status(400).json({ error: 'user_id is required' }); } if (!current_step) { return res.status(400).json({ error: 'current_step is required' }); } if (!data || !Array.isArray(data)) { return res.status(400).json({ error: 'data must be an array' }); } const pool = req.app.locals.pool; if (!pool) { throw new Error('Database pool not initialized'); } // Upsert: insert or update the unnamed session for this user const result = await pool.query(` INSERT INTO import_sessions ( user_id, name, current_step, data, product_images, global_selections, validation_state ) VALUES ($1, NULL, $2, $3, $4, $5, $6) ON CONFLICT (user_id) WHERE name IS NULL DO UPDATE SET current_step = EXCLUDED.current_step, data = EXCLUDED.data, product_images = EXCLUDED.product_images, global_selections = EXCLUDED.global_selections, validation_state = EXCLUDED.validation_state, updated_at = CURRENT_TIMESTAMP RETURNING id, user_id, name, current_step, created_at, updated_at `, [ user_id, current_step, JSON.stringify(data), product_images ? JSON.stringify(product_images) : null, global_selections ? JSON.stringify(global_selections) : null, validation_state ? JSON.stringify(validation_state) : null ]); res.json(result.rows[0]); } catch (error) { console.error('Error autosaving import session:', error); res.status(500).json({ error: 'Failed to autosave import session', details: error instanceof Error ? error.message : 'Unknown error' }); } }); // Delete unnamed session for user (clear autosave) // IMPORTANT: This must be defined before /:id routes router.delete('/autosave/:user_id', async (req, res) => { try { const { user_id } = req.params; const pool = req.app.locals.pool; if (!pool) { throw new Error('Database pool not initialized'); } const result = await pool.query( 'DELETE FROM import_sessions WHERE user_id = $1 AND name IS NULL RETURNING id, user_id, name, current_step, created_at, updated_at', [user_id] ); if (result.rows.length === 0) { return res.status(404).json({ error: 'No autosave session found for user' }); } res.json({ message: 'Autosave session deleted successfully' }); } catch (error) { console.error('Error deleting autosave session:', error); res.status(500).json({ error: 'Failed to delete autosave session', details: error instanceof Error ? error.message : 'Unknown error' }); } }); // Create new named session router.post('/', async (req, res) => { try { const { user_id, name, current_step, data, product_images, global_selections, validation_state } = req.body; // Validate required fields if (!user_id) { return res.status(400).json({ error: 'user_id is required' }); } if (!name || typeof name !== 'string' || name.trim().length === 0) { return res.status(400).json({ error: 'name is required for creating a named session' }); } if (!current_step) { return res.status(400).json({ error: 'current_step is required' }); } if (!data || !Array.isArray(data)) { return res.status(400).json({ error: 'data must be an array' }); } const pool = req.app.locals.pool; if (!pool) { throw new Error('Database pool not initialized'); } const result = await pool.query(` INSERT INTO import_sessions ( user_id, name, current_step, data, product_images, global_selections, validation_state ) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING id, user_id, name, current_step, created_at, updated_at `, [ user_id, name.trim(), current_step, JSON.stringify(data), product_images ? JSON.stringify(product_images) : null, global_selections ? JSON.stringify(global_selections) : null, validation_state ? JSON.stringify(validation_state) : null ]); res.status(201).json(result.rows[0]); } catch (error) { console.error('Error creating import session:', error); res.status(500).json({ error: 'Failed to create import session', details: error instanceof Error ? error.message : 'Unknown error' }); } }); // Update named session by ID router.put('/:id', async (req, res) => { try { const { id } = req.params; const { name, current_step, data, product_images, global_selections, validation_state } = req.body; if (!current_step) { return res.status(400).json({ error: 'current_step is required' }); } if (!data || !Array.isArray(data)) { return res.status(400).json({ error: 'data must be an array' }); } const pool = req.app.locals.pool; if (!pool) { throw new Error('Database pool not initialized'); } // Build update query - optionally include name if provided const hasName = name !== undefined; const result = await pool.query(` UPDATE import_sessions SET ${hasName ? 'name = $1,' : ''} current_step = $${hasName ? 2 : 1}, data = $${hasName ? 3 : 2}, product_images = $${hasName ? 4 : 3}, global_selections = $${hasName ? 5 : 4}, validation_state = $${hasName ? 6 : 5}, updated_at = CURRENT_TIMESTAMP WHERE id = $${hasName ? 7 : 6} RETURNING id, user_id, name, current_step, created_at, updated_at `, hasName ? [ typeof name === 'string' ? name.trim() : name, current_step, JSON.stringify(data), product_images ? JSON.stringify(product_images) : null, global_selections ? JSON.stringify(global_selections) : null, validation_state ? JSON.stringify(validation_state) : null, id ] : [ current_step, JSON.stringify(data), product_images ? JSON.stringify(product_images) : null, global_selections ? JSON.stringify(global_selections) : null, validation_state ? JSON.stringify(validation_state) : null, id ]); if (result.rows.length === 0) { return res.status(404).json({ error: 'Import session not found' }); } res.json(result.rows[0]); } catch (error) { console.error('Error updating import session:', error); res.status(500).json({ error: 'Failed to update import session', details: error instanceof Error ? error.message : 'Unknown error' }); } }); // Delete session by ID router.delete('/:id', async (req, res) => { try { const { id } = req.params; const pool = req.app.locals.pool; if (!pool) { throw new Error('Database pool not initialized'); } const result = await pool.query('DELETE FROM import_sessions WHERE id = $1 RETURNING id, user_id, name, current_step, created_at, updated_at', [id]); if (result.rows.length === 0) { return res.status(404).json({ error: 'Import session not found' }); } res.json({ message: 'Import session deleted successfully' }); } catch (error) { console.error('Error deleting import session:', error); res.status(500).json({ error: 'Failed to delete import session', details: error instanceof Error ? error.message : 'Unknown error' }); } }); // Error handling middleware router.use((err, req, res, next) => { console.error('Import sessions route error:', err); res.status(500).json({ error: 'Internal server error', details: err.message }); }); module.exports = router;