/**
 * Assignment Controller
 * API endpoints for specialization paths and daily assignments
 */

const assignmentService = require('../services/assignmentService');
const db = require('../db');
const { 
    SPECIALIZATION_PATHS, 
    LEVEL_CONFIG,
    getPathsForDropdown 
} = require('../config/specializationPaths');

/**
 * GET /api/assignments/paths
 * Get all available specialization paths
 */
async function getSpecializationPaths(req, res) {
    try {
        const paths = getPathsForDropdown();
        res.json({
            success: true,
            paths,
            foundationsEndLevel: LEVEL_CONFIG.FOUNDATIONS_END,
            pathSelectionLevel: LEVEL_CONFIG.PATH_SELECTION_LEVEL
        });
    } catch (error) {
        console.error('Error getting specialization paths:', error);
        res.status(500).json({ success: false, error: 'Failed to get paths' });
    }
}

/**
 * GET /api/assignments/user-paths
 * Get current user's path selections
 */
async function getUserPaths(req, res) {
    try {
        const userId = Number(req.user.id);
        const paths = await assignmentService.getUserPaths(userId);
        const level = await assignmentService.getUserLevel(userId);
        const stats = await assignmentService.getUserSpecializationStats(userId);
        const shouldPrompt = await assignmentService.shouldPromptPathSelection(userId);

        res.json({
            success: true,
            ...paths,
            current_level: level,
            specialization_stats: stats,
            should_prompt_path_selection: shouldPrompt,
            is_in_foundations: level <= LEVEL_CONFIG.FOUNDATIONS_END
        });
    } catch (error) {
        console.error('Error getting user paths:', error);
        res.status(500).json({ success: false, error: 'Failed to get user paths' });
    }
}

/**
 * PUT /api/assignments/user-paths
 * Update user's specialization paths
 */
async function updateUserPaths(req, res) {
    try {
        const userId = Number(req.user.id);
        const { primary_path, secondary_path } = req.body;

        if (!primary_path) {
            return res.status(400).json({ 
                success: false, 
                error: 'Primary path is required' 
            });
        }

        const result = await assignmentService.updateUserPaths(
            userId, 
            primary_path, 
            secondary_path || null
        );

        res.json({
            success: true,
            message: 'Paths updated successfully',
            ...result
        });
    } catch (error) {
        console.error('Error updating user paths:', error);
        res.status(400).json({ 
            success: false, 
            error: error.message || 'Failed to update paths' 
        });
    }
}

/**
 * GET /api/assignments/daily-queue
 * Get or generate today's alert queue for the user
 */
async function getDailyQueue(req, res) {
    try {
        const userId = Number(req.user.id);
        const queue = await assignmentService.generateDailyQueue(userId);

        const completed = queue.filter(a => a.completed).length;
        const total = queue.length;

        // If queue is empty, fetch random alerts from DB to prevent "hardcoded" fallback in frontend
        if (queue.length === 0) {
            console.log('[getDailyQueue] Queue empty, fetching random alerts for training...');
            // Optimization: Avoid ORDER BY RAND() on large tables by using a random offset based on max ID
            const maxIdResult = await db.query('SELECT MAX(id) as max_id FROM alerts');
            const maxId = maxIdResult.rows[0]?.max_id || 1000;
            const randomOffset = Math.floor(Math.random() * Math.max(1, maxId - 100));

            const fallbackAlerts = await db.query(`
                SELECT 
                    a.id as alert_id,
                    a.id as assignment_id, 
                    a.title,
                    a.severity,
                    a.source,
                    a.details,
                    a.path_code,
                    a.min_level,
                    a.difficulty,
                    0 as completed,
                    0 as is_replay
                FROM alerts a
                WHERE a.id >= ? 
                  AND NOT EXISTS (SELECT 1 FROM operation_alerts oa WHERE oa.alert_id = a.id)
                LIMIT 10
            `, [randomOffset]);
            
            if (fallbackAlerts.rows && fallbackAlerts.rows.length > 0) {
                 res.json({
                    success: true,
                    queue: fallbackAlerts.rows,
                    stats: {
                        total: fallbackAlerts.rows.length,
                        completed: 0,
                        remaining: fallbackAlerts.rows.length,
                        completion_percentage: 0
                    }
                });
                return;
            }
        }

        res.json({
            success: true,
            queue,
            stats: {
                total,
                completed,
                remaining: total - completed,
                completion_percentage: total > 0 ? Math.round((completed / total) * 100) : 0
            }
        });
    } catch (error) {
        console.error('Error getting daily queue:', error);
        res.status(500).json({ success: false, error: 'Failed to get daily queue' });
    }
}

/**
 * POST /api/assignments/:alertId/complete
 * Mark an assignment as completed
 */
async function completeAssignment(req, res) {
    try {
        const userId = Number(req.user.id);
        const alertId = parseInt(req.params.alertId);
        const { xp_earned = 0 } = req.body;

        await assignmentService.markAssignmentCompleted(userId, alertId, xp_earned);

        res.json({
            success: true,
            message: 'Assignment marked as completed'
        });
    } catch (error) {
        console.error('Error completing assignment:', error);
        res.status(500).json({ success: false, error: 'Failed to complete assignment' });
    }
}

/**
 * GET /api/assignments/stats
 * Get user's specialization statistics
 */
async function getSpecializationStats(req, res) {
    try {
        const userId = Number(req.user.id);
        const stats = await assignmentService.getUserSpecializationStats(userId);
        const level = await assignmentService.getUserLevel(userId);

        res.json({
            success: true,
            current_level: level,
            specializations: stats,
            total_paths_started: stats.length
        });
    } catch (error) {
        console.error('Error getting specialization stats:', error);
        res.status(500).json({ success: false, error: 'Failed to get stats' });
    }
}

/**
 * GET /api/assignments/available-alerts
 * Get alerts available to user based on level and path
 */
async function getAvailableAlerts(req, res) {
    try {
        const userId = Number(req.user.id);
        const { 
            limit = 20, 
            offset = 0, 
            path = null, 
            show_locked = 'false' 
        } = req.query;

        const alerts = await assignmentService.getAvailableAlerts(userId, {
            limit: parseInt(limit),
            offset: parseInt(offset),
            pathFilter: path,
            showLocked: show_locked === 'true'
        });

        res.json({
            success: true,
            alerts,
            count: alerts.length
        });
    } catch (error) {
        console.error('Error getting available alerts:', error);
        res.status(500).json({ success: false, error: 'Failed to get alerts' });
    }
}

/**
 * POST /api/assignments/generate-queue
 * Force regenerate today's alert queue
 */
async function generateQueue(req, res) {
    try {
        const userId = Number(req.user.id);
        const queue = await assignmentService.generateDailyQueue(userId);

        const completed = queue.filter(a => a.completed).length;
        const total = queue.length;

        res.json({
            success: true,
            message: 'Queue generated successfully',
            queue,
            stats: {
                total,
                completed,
                remaining: total - completed,
                completion_percentage: total > 0 ? Math.round((completed / total) * 100) : 0
            }
        });
    } catch (error) {
        console.error('Error generating queue:', error);
        res.status(500).json({ success: false, error: 'Failed to generate queue' });
    }
}

/**
 * GET /api/assignments/my
 * Get all active assignments (Alerts, Paths, CTFs) for the user
 */
async function getMyAssignments(req, res) {
    try {
        const userId = Number(req.user.id);

        // 1. Fetch Assigned Alerts (Investigations)
        const alertsQuery = await db.query(`
            SELECT 
                i.id as assignment_id,
                i.status,
                i.created_at as assigned_date,
                i.due_date,
                a.id as alert_id,
                a.title,
                a.severity,
                a.details,
                a.difficulty,
                'alert' as type,
                '30m' as duration
            FROM investigations i
            JOIN alerts a ON i.alert_id = a.id
            WHERE i.user_id = ? AND i.status = 'pending'
            ORDER BY i.created_at DESC
        `, [userId]);

        // 2. Fetch Learning Path & CTF Assignments
        const pathsQuery = await db.query(`
            SELECT 
                opa.id as assignment_id,
                opa.is_mandatory,
                opa.due_date,
                opa.operation_id,
                opa.learning_path_id,
                CASE 
                    WHEN opa.operation_id IS NOT NULL THEN (SELECT title FROM operations WHERE id = opa.operation_id)
                    ELSE (SELECT title FROM learning_paths WHERE id = opa.learning_path_id)
                END as title,
                CASE 
                    WHEN opa.operation_id IS NOT NULL THEN (SELECT description FROM operations WHERE id = opa.operation_id)
                    ELSE (SELECT description FROM learning_paths WHERE id = opa.learning_path_id)
                END as details,
                'path' as type,
                'High' as severity,
                '1h' as duration
            FROM organization_path_assignments opa
            WHERE opa.user_id = ? 
            AND (opa.completed_at IS NULL)
            HAVING title IS NOT NULL
        `, [userId]);

        // Combine results
        const allAssignments = [
            ...alertsQuery.rows.map(row => ({
                ...row,
                source: 'investigation'
            })),
            ...pathsQuery.rows.map(row => ({
                ...row,
                severity: row.is_mandatory ? 'Critical' : 'High',
                source: row.operation_id ? 'ctf' : 'learning_path'
            }))
        ];

        // Deduplicate assignments based on their unique content source
        // (If assigned multiple times, show only one)
        const uniqueAssignments = [];
        const seen = new Set();

        for (const assignment of allAssignments) {
            // Skip invalid assignments (just in case query checked, but good double check)
            if (!assignment.title) continue;

            let key;
            if (assignment.type === 'alert') {
                key = `alert-${assignment.alert_id}`;
            } else if (assignment.operation_id) {
                key = `ctf-${assignment.operation_id}`;
            } else {
                key = `path-${assignment.learning_path_id}`;
            }

            if (!seen.has(key)) {
                seen.add(key);
                uniqueAssignments.push(assignment);
            }
        }

        res.json({
            success: true,
            assignments: uniqueAssignments
        });
    } catch (error) {
        console.error('Error getting my assignments:', error);
        res.status(500).json({ success: false, error: 'Failed to get assignments' });
    }
}

module.exports = {
    getSpecializationPaths,
    getUserPaths,
    updateUserPaths,
    getDailyQueue,
    generateQueue,
    completeAssignment,
    getSpecializationStats,
    getAvailableAlerts,
    getMyAssignments
};
