const express = require('express'); const router = express.Router(); const { callAI } = require('../utils/ai'); const PROMPTS = require('../utils/prompts'); const { authMiddleware } = require('../middleware/auth'); const db = require('../db/database'); var logger = require('../utils/logger'); var { wrapUserText, INJECTION_GUARD } = require('../utils/promptSafe'); // Get all milestones for client (authenticated users) router.get('/milestones-data', authMiddleware, async (req, res) => { try { const result = await db.query( 'SELECT * FROM developmental_milestones ORDER BY age_group, domain, sort_order, id' ); // Group by age_group and domain to match the static data structure const grouped = {}; result.rows.forEach(row => { if (!grouped[row.age_group]) { grouped[row.age_group] = {}; } if (!grouped[row.age_group][row.domain]) { grouped[row.age_group][row.domain] = []; } grouped[row.age_group][row.domain].push(row.milestone_text); }); res.json({ success: true, milestones: grouped }); } catch (err) { res.status(500).json({ error: 'Request failed' }); } }); // Narrative format router.post('/generate-milestone-narrative', authMiddleware, async (req, res) => { try { const { milestones, ageGroup, patientAge, patientGender, model, format } = req.body; if (!milestones) return res.status(400).json({ error: 'No milestones' }); const achieved = milestones.filter(m => m.status === 'yes'); const notAchieved = milestones.filter(m => m.status === 'no'); const notAssessed = milestones.filter(m => m.status === null); if (achieved.length === 0 && notAchieved.length === 0) { return res.json({ success: true, narrative: 'No developmental milestones were assessed during this visit.', summary: { achieved: 0, notAchieved: 0, notAssessed: notAssessed.length } }); } let milestoneText = ''; if (achieved.length > 0) { milestoneText += 'ACHIEVED:\n'; achieved.forEach(m => { milestoneText += ` - [${m.domain}] ${m.milestone}\n`; }); } if (notAchieved.length > 0) { milestoneText += '\nNOT YET ACHIEVED:\n'; notAchieved.forEach(m => { milestoneText += ` - [${m.domain}] ${m.milestone}\n`; }); } // Choose narrative or list format const prompt = (format === 'list') ? PROMPTS.milestoneList : PROMPTS.milestoneNarrative; const result = await callAI([ { role: 'system', content: prompt + INJECTION_GUARD }, { role: 'user', content: `Patient: ${patientAge || 'Unknown'}, ${patientGender || 'Unknown'}\nAge Group: ${ageGroup}\n\n` + wrapUserText('milestones', milestoneText) + `\n\nAssessed: ${achieved.length + notAchieved.length} | Achieved: ${achieved.length} | Not achieved: ${notAchieved.length} | Not assessed (OMIT): ${notAssessed.length}` } ], { model }); res.json({ success: true, narrative: result.content, model: result.model, summary: { achieved: achieved.length, notAchieved: notAchieved.length, notAssessed: notAssessed.length } }); logger.audit(req.user.id, 'generate_milestone_narrative', 'Generated milestone narrative', req, { category: 'clinical' }); } catch (err) { res.status(500).json({ error: 'Request failed' }); } }); // 3-sentence summary router.post('/generate-milestone-summary', authMiddleware, async (req, res) => { try { const { narrative, ageGroup, patientAge, patientGender, model } = req.body; if (!narrative) return res.status(400).json({ error: 'No narrative' }); const result = await callAI([ { role: 'system', content: PROMPTS.milestoneSummary + INJECTION_GUARD }, { role: 'user', content: `Patient: ${patientAge || 'Unknown'}, ${patientGender || 'Unknown'}\nAge Group: ${ageGroup}\n\nNARRATIVE:\n` + wrapUserText('narrative', narrative) } ], { model, maxTokens: 500 }); res.json({ success: true, summary: result.content, model: result.model }); logger.audit(req.user.id, 'generate_milestone_summary', 'Generated milestone summary', req, { category: 'clinical' }); } catch (err) { res.status(500).json({ error: 'Request failed' }); } }); module.exports = router;