const express = require('express'); const router = express.Router(); const database = require('../config/database'); const Feature = require('../models/feature'); const Template = require('../models/template'); // POST /api/learning/feature-selected - Track feature selection for learning router.post('/feature-selected', async (req, res) => { try { const { template_id, feature_id, user_session, project_id } = req.body; console.log(`🧠 Learning: Feature selected - ${feature_id} for template ${template_id}`); // Validate required fields if (!template_id || !feature_id) { return res.status(400).json({ success: false, error: 'Missing required fields', message: 'template_id and feature_id are required' }); } // Record the selection const query = ` INSERT INTO feature_usage (template_id, feature_id, user_session, project_id) VALUES ($1, $2, $3, $4) RETURNING * `; const result = await database.query(query, [template_id, feature_id, user_session, project_id]); // Update feature usage count const updateQuery = ` UPDATE template_features SET usage_count = usage_count + 1 WHERE id = $1 `; await database.query(updateQuery, [feature_id]); res.json({ success: true, data: result.rows[0], message: 'Feature selection recorded for learning system' }); } catch (error) { console.error('❌ Error recording feature selection:', error.message); res.status(500).json({ success: false, error: 'Failed to record feature selection', message: error.message }); } }); // GET /api/learning/recommendations/:templateId - Get AI-powered recommendations router.get('/recommendations/:templateId', async (req, res) => { try { const { templateId } = req.params; const limit = parseInt(req.query.limit) || 5; console.log(`🤖 Generating recommendations for template: ${templateId}`); // Get template info const template = await Template.getByIdWithFeatures(templateId); if (!template) { return res.status(404).json({ success: false, error: 'Template not found', message: `Template with ID ${templateId} does not exist` }); } // Get popular features from similar templates (same category) const similarFeaturesQuery = ` SELECT tf.*, t.title as template_title, t.type as template_type FROM template_features tf JOIN templates t ON tf.template_id = t.id WHERE t.category = ( SELECT category FROM templates WHERE id = $1 ) AND tf.template_id != $1 AND tf.usage_count > 0 ORDER BY tf.usage_count DESC, tf.user_rating DESC LIMIT $2 `; const similarFeatures = await database.query(similarFeaturesQuery, [templateId, limit]); // Get trending features (high recent usage) const trendingQuery = ` SELECT tf.*, t.title as template_title, COUNT(fu.id) as recent_usage FROM template_features tf JOIN templates t ON tf.template_id = t.id LEFT JOIN feature_usage fu ON tf.id = fu.feature_id AND fu.selected_at > NOW() - INTERVAL '30 days' WHERE tf.template_id != $1 GROUP BY tf.id, t.title HAVING COUNT(fu.id) > 0 ORDER BY recent_usage DESC, tf.user_rating DESC LIMIT $2 `; const trendingFeatures = await database.query(trendingQuery, [templateId, limit]); // Get complementary features (often used together) const complementaryQuery = ` WITH template_sessions AS ( SELECT DISTINCT user_session FROM feature_usage WHERE template_id = $1 AND user_session IS NOT NULL ) SELECT tf.*, t.title as template_title, COUNT(DISTINCT ts.user_session) as co_occurrence FROM template_sessions ts JOIN feature_usage fu ON ts.user_session = fu.user_session JOIN template_features tf ON fu.feature_id = tf.id JOIN templates t ON tf.template_id = t.id WHERE tf.template_id != $1 GROUP BY tf.id, t.title ORDER BY co_occurrence DESC, tf.user_rating DESC LIMIT $2 `; const complementaryFeatures = await database.query(complementaryQuery, [templateId, limit]); const recommendations = { similar_features: similarFeatures.rows, trending_features: trendingFeatures.rows, complementary_features: complementaryFeatures.rows, template_info: { id: template.id, title: template.title, category: template.category, existing_features_count: template.features ? template.features.length : 0 } }; res.json({ success: true, data: recommendations, message: `Generated ${Object.keys(recommendations).length - 1} types of recommendations for ${template.title}` }); } catch (error) { console.error('❌ Error generating recommendations:', error.message); res.status(500).json({ success: false, error: 'Failed to generate recommendations', message: error.message }); } }); // POST /api/learning/analyze-usage - Analyze usage patterns router.post('/analyze-usage', async (req, res) => { try { const { template_id, time_period = '30 days' } = req.body; console.log(`📊 Analyzing usage patterns for template: ${template_id || 'all'}`); let templateFilter = ''; const params = [time_period]; if (template_id) { templateFilter = 'AND fu.template_id = $2'; params.push(template_id); } // Usage trends over time const trendsQuery = ` SELECT DATE(fu.selected_at) as date, COUNT(*) as selections, COUNT(DISTINCT fu.user_session) as unique_sessions FROM feature_usage fu WHERE fu.selected_at > NOW() - INTERVAL '${time_period}' ${templateFilter} GROUP BY DATE(fu.selected_at) ORDER BY date DESC LIMIT 30 `; // Most popular features const popularQuery = ` SELECT tf.name, tf.feature_type, tf.complexity, COUNT(fu.id) as usage_count, COUNT(DISTINCT fu.user_session) as unique_users, t.title as template_title FROM feature_usage fu JOIN template_features tf ON fu.feature_id = tf.id JOIN templates t ON fu.template_id = t.id WHERE fu.selected_at > NOW() - INTERVAL '${time_period}' ${templateFilter} GROUP BY tf.id, tf.name, tf.feature_type, tf.complexity, t.title ORDER BY usage_count DESC LIMIT 20 `; // Feature type distribution const distributionQuery = ` SELECT tf.feature_type, tf.complexity, COUNT(fu.id) as selections, COUNT(DISTINCT fu.user_session) as unique_users FROM feature_usage fu JOIN template_features tf ON fu.feature_id = tf.id WHERE fu.selected_at > NOW() - INTERVAL '${time_period}' ${templateFilter} GROUP BY tf.feature_type, tf.complexity ORDER BY selections DESC `; const [trendsResult, popularResult, distributionResult] = await Promise.all([ database.query(trendsQuery, params), database.query(popularQuery, params), database.query(distributionQuery, params) ]); const analysis = { time_period, template_id: template_id || 'all', usage_trends: trendsResult.rows, popular_features: popularResult.rows, feature_distribution: distributionResult.rows, summary: { total_trends: trendsResult.rows.length, top_features: popularResult.rows.length, distribution_segments: distributionResult.rows.length } }; res.json({ success: true, data: analysis, message: `Usage analysis completed for ${time_period} period` }); } catch (error) { console.error('❌ Error analyzing usage patterns:', error.message); res.status(500).json({ success: false, error: 'Failed to analyze usage patterns', message: error.message }); } }); // GET /api/learning/insights - Get learning system insights router.get('/insights', async (req, res) => { try { console.log('🔍 Gathering learning system insights...'); // Overall statistics const statsQuery = ` SELECT COUNT(DISTINCT fu.template_id) as active_templates, COUNT(DISTINCT fu.feature_id) as features_used, COUNT(DISTINCT fu.user_session) as unique_sessions, COUNT(*) as total_selections FROM feature_usage fu WHERE fu.selected_at > NOW() - INTERVAL '30 days' `; // Growth metrics const growthQuery = ` SELECT DATE_TRUNC('week', fu.selected_at) as week, COUNT(*) as selections, COUNT(DISTINCT fu.user_session) as users FROM feature_usage fu WHERE fu.selected_at > NOW() - INTERVAL '12 weeks' GROUP BY DATE_TRUNC('week', fu.selected_at) ORDER BY week DESC `; // Learning effectiveness const effectivenessQuery = ` SELECT AVG(tf.user_rating) as avg_rating, SUM(CASE WHEN tf.created_by_user = true THEN 1 ELSE 0 END) as user_contributed_features, SUM(CASE WHEN tf.is_default = true THEN 1 ELSE 0 END) as default_features FROM template_features tf `; const [statsResult, growthResult, effectivenessResult] = await Promise.all([ database.query(statsQuery), database.query(growthQuery), database.query(effectivenessQuery) ]); const insights = { overview: statsResult.rows[0], growth_trends: growthResult.rows, learning_effectiveness: effectivenessResult.rows[0], generated_at: new Date().toISOString() }; res.json({ success: true, data: insights, message: 'Learning system insights generated successfully' }); } catch (error) { console.error('❌ Error gathering insights:', error.message); res.status(500).json({ success: false, error: 'Failed to gather learning insights', message: error.message }); } }); module.exports = router;