const express = require('express'); const router = express.Router(); const { getDb, ensureUserDefaultCategories } = require('../db/database'); const { standardizeError } = require('../middleware/errorFormatter'); const { createSubscriptionFromRecommendation, decorateSubscription, getSubscriptionRecommendations, getSubscriptionSummary, getSubscriptions, } = require('../services/subscriptionService'); router.get('/', (req, res) => { const db = getDb(); ensureUserDefaultCategories(req.user.id); const subscriptions = getSubscriptions(db, req.user.id); res.json({ summary: getSubscriptionSummary(subscriptions), subscriptions, }); }); router.get('/recommendations', (req, res) => { const db = getDb(); res.json({ recommendations: getSubscriptionRecommendations(db, req.user.id), }); }); router.post('/recommendations/create', (req, res) => { const db = getDb(); ensureUserDefaultCategories(req.user.id); if (req.body?.category_id) { const categoryId = parseInt(req.body.category_id, 10); const category = Number.isInteger(categoryId) ? db.prepare('SELECT id FROM categories WHERE id = ? AND user_id = ? AND deleted_at IS NULL').get(categoryId, req.user.id) : null; if (!category) { return res.status(400).json(standardizeError('category_id is invalid for this user', 'VALIDATION_ERROR', 'category_id')); } } try { const created = createSubscriptionFromRecommendation(db, req.user.id, req.body || {}); res.status(201).json(created); } catch (err) { res.status(err.status || 400).json(standardizeError(err.message || 'Could not create subscription', err.status ? 'VALIDATION_ERROR' : 'SUBSCRIPTION_CREATE_ERROR', err.field || null)); } }); router.patch('/:id', (req, res) => { const db = getDb(); const billId = parseInt(req.params.id, 10); if (!Number.isInteger(billId)) { return res.status(400).json(standardizeError('bill_id must be an integer', 'VALIDATION_ERROR', 'bill_id')); } const existing = db.prepare('SELECT * FROM bills WHERE id = ? AND user_id = ? AND deleted_at IS NULL').get(billId, req.user.id); if (!existing) return res.status(404).json(standardizeError('Bill not found', 'NOT_FOUND', 'bill_id')); const allowedTypes = new Set(['streaming', 'software', 'cloud', 'music', 'news', 'fitness', 'gaming', 'utilities', 'insurance', 'other']); const next = { is_subscription: req.body.is_subscription !== undefined ? (req.body.is_subscription ? 1 : 0) : existing.is_subscription, subscription_type: req.body.subscription_type !== undefined ? (allowedTypes.has(req.body.subscription_type) ? req.body.subscription_type : 'other') : existing.subscription_type, reminder_days_before: req.body.reminder_days_before !== undefined ? Number(req.body.reminder_days_before) : existing.reminder_days_before, active: req.body.active !== undefined ? (req.body.active ? 1 : 0) : existing.active, }; if (!Number.isInteger(next.reminder_days_before) || next.reminder_days_before < 0 || next.reminder_days_before > 30) { return res.status(400).json(standardizeError('reminder_days_before must be between 0 and 30', 'VALIDATION_ERROR', 'reminder_days_before')); } db.prepare(` UPDATE bills SET is_subscription = ?, subscription_type = ?, reminder_days_before = ?, active = ?, updated_at = datetime('now') WHERE id = ? AND user_id = ? `).run(next.is_subscription, next.subscription_type, next.reminder_days_before, next.active, billId, req.user.id); const updated = db.prepare(` SELECT b.*, c.name AS category_name FROM bills b LEFT JOIN categories c ON c.id = b.category_id AND c.user_id = b.user_id AND c.deleted_at IS NULL WHERE b.id = ? AND b.user_id = ? `).get(billId, req.user.id); res.json(decorateSubscription(updated)); }); module.exports = router;