
const db = require('../db');

// All available action options
const ACTION_OPTIONS = [
    { id: 'block', label: 'BLOCK IP' },
    { id: 'isolate', label: 'ISOLATE HOST' },
    { id: 'lock', label: 'LOCK ACCOUNT' },
    { id: 'purge', label: 'PURGE INBOX' }
];

/**
 * Check if user has already played Crisis Mode today
 * Uses JS Date comparison to be timezone-safe (relies on Server System Time)
 */
const hasPlayedToday = async (userId) => {
    const result = await db.query(
        `SELECT started_at FROM user_operation_progress 
         WHERE user_id = ? 
         ORDER BY started_at DESC 
         LIMIT 1`,
        [userId]
    );
    
    if (result.rows.length === 0) return false;
    
    const lastPlayed = new Date(result.rows[0].started_at);
    const now = new Date();
    
    // Compare dates in the server's local timezone
    return lastPlayed.toDateString() === now.toDateString();
};

/**
 * Start a Crisis: Pick a random Operation and return its details + alerts
 * LIMIT: 1 crisis per day
 */
exports.startCrisis = async (req, res) => {
    try {
        const userId = Number(req.user.id);

        // Check daily limit
        const alreadyPlayed = await hasPlayedToday(userId);
        if (alreadyPlayed) {
            return res.status(429).json({ 
                error: 'DAILY_LIMIT_REACHED',
                message: 'You have already completed today\'s Crisis Simulation. Come back tomorrow!'
            });
        }

        // 1. Pick a random active operation
        const opsResult = await db.query(
            "SELECT id, title, description, story_intro, difficulty_level, apt_group FROM operations WHERE is_active = 1 ORDER BY RAND() LIMIT 1"
        );
        const ops = opsResult.rows;

        if (ops.length === 0) {
            return res.status(404).json({ error: 'No active operations found for crisis mode.' });
        }

        const operation = ops[0];

        // 2. Fetch linked alerts for this operation (limit 5 for short crisis)
        const alertsResult = await db.query(
            `SELECT a.id, a.title, a.severity, a.source, a.details, a.alert_type, a.playbook_solution 
             FROM operation_alerts oa
             JOIN alerts a ON oa.alert_id = a.id
             WHERE oa.operation_id = ?
             ORDER BY oa.sequence_order ASC
             LIMIT 5`,
            [operation.id]
        );
        const alerts = alertsResult.rows;
        
        if (alerts.length === 0) {
            return res.status(404).json({ error: 'This operation has no active alerts for crisis response.' });
        }

        // 3. Transform alerts for quiz format
        const quizAlerts = alerts.map(a => {
            // Parse playbook_solution
            let solution = {};
            if (a.playbook_solution) {
                if (typeof a.playbook_solution === 'string') {
                    try { solution = JSON.parse(a.playbook_solution); } catch(e) {}
                } else {
                    solution = a.playbook_solution;
                }
            }
            
            let correctAction = solution.correct_action;
            let explanation = solution.explanation;
            
            // Smart fallback if no playbook solution exists
            if (!correctAction) {
                const titleLower = (a.title || '').toLowerCase();
                const typeLower = (a.alert_type || '').toLowerCase();
                const detailLower = (a.details || '').toLowerCase();
                const sourceLower = (a.source || '').toLowerCase();
                
                // 1. Phishing / Email -> Purge Inbox
                if (titleLower.includes('phish') || typeLower.includes('email') || sourceLower.includes('email') || detailLower.includes('sender')) {
                    correctAction = 'purge';
                    if (!explanation) explanation = "Phishing emails and suspicious messages must be immediately purged from the user's inbox to prevent accidental clicks on malicious links or attachments.";
                } 
                // 2. Malware / Endpoint / Backdoor -> Isolate Host
                else if (
                    titleLower.includes('malware') || 
                    titleLower.includes('ransom') || 
                    titleLower.includes('backdoor') || 
                    titleLower.includes('trojan') || 
                    titleLower.includes('virus') || 
                    titleLower.includes('rootkit') ||
                    typeLower.includes('endpoint') || 
                    sourceLower.includes('edr') || 
                    sourceLower.includes('av') || 
                    detailLower.includes('process') || 
                    detailLower.includes('registry')
                ) {
                    correctAction = 'isolate';
                    if (!explanation) explanation = "When a host is compromised by malware, rootkits, or persistence mechanisms, it must be ISOLATED from the network immediately to prevent lateral movement and Command & Control (C2) communication.";
                } 
                // 3. Identity / Login -> Lock Account
                else if (
                    titleLower.includes('brute') || 
                    titleLower.includes('login') || 
                    titleLower.includes('password') || 
                    titleLower.includes('credential') || 
                    titleLower.includes('user') || 
                    titleLower.includes('account') || 
                    typeLower.includes('identity') || 
                    sourceLower.includes('iam') || 
                    sourceLower.includes('ad')
                ) {
                    correctAction = 'lock';
                    if (!explanation) explanation = "Suspicious login attempts, brute force attacks, or compromised credentials require immediate ACCOUNT LOCKOUT to prevent unauthorized access to the environment.";
                } 
                // 4. Network / C2 / Exfil -> Block IP
                else {
                    correctAction = 'block'; 
                    if (!explanation) explanation = "Network-based threats, such as C2 traffic, data exfiltration, or scanning from external IPs, should be mitigated by BLOCKING the malicious IP address at the firewall.";
                }
            }

            // Fallback explanation if correctAction exists but no explanation
            if (!explanation && correctAction) {
                 if (correctAction === 'isolate') explanation = "This threat description indicates system compromise, which typically requires host isolation to contain.";
                 else if (correctAction === 'block') explanation = "This threat involves network communication that should be mitigated by blocking the source or destination IP.";
                 else if (correctAction === 'lock') explanation = "This threat involves compromised or targeted user credentials, requiring an account lockout.";
                 else if (correctAction === 'purge') explanation = "This threat involves malicious email content that must be purged from the environment.";
            }
            
            return {
                id: a.id,
                title: a.title,
                severity: a.severity,
                source: a.source,
                details: a.details,
                alertType: a.alert_type,
                // Quiz data
                options: ACTION_OPTIONS,
                correctAction: correctAction,
                explanation: explanation
            };
        });

        // 4. Record that user started a crisis today
        await db.query(
            `INSERT INTO user_operation_progress (user_id, operation_id, started_at) VALUES (?, ?, NOW())`,
            [userId, operation.id]
        );

        // 5. Construct the Crisis Object
        const crisisData = {
            sessionId: Date.now().toString(),
            operation: {
                id: operation.id,
                title: operation.title,
                description: operation.description,
                intro: operation.story_intro,
                apt: operation.apt_group,
                difficulty: operation.difficulty_level
            },
            alerts: quizAlerts,
            timeLimitSeconds: 600,
            startedAt: new Date().toISOString()
        };

        res.json(crisisData);

    } catch (error) {
        console.error('Crisis Start Error:', error);
        res.status(500).json({ error: 'Failed to start crisis' });
    }
};

/**
 * Submit Crisis Results
 * Calculates XP based on correct answers
 */
exports.submitCrisis = async (req, res) => {
    try {
        const userId = Number(req.user.id);
        const { operationId, answers } = req.body;
        // answers: { [alertId]: 'block'|'isolate'|'lock'|'purge' }

        if (!answers || typeof answers !== 'object') {
            return res.status(400).json({ error: 'Invalid answers format' });
        }

        // Fetch correct answers from DB
        const alertIds = Object.keys(answers);
        if (alertIds.length === 0) {
            return res.status(400).json({ error: 'No answers provided' });
        }

        const alertsResult = await db.query(
            `SELECT id, playbook_solution FROM alerts WHERE id IN (${alertIds.map(() => '?').join(',')})`,
            alertIds
        );

        let correctCount = 0;
        const totalCount = alertIds.length;

        for (const alert of alertsResult.rows) {
            let solution = {};
            if (alert.playbook_solution) {
                if (typeof alert.playbook_solution === 'string') {
                    try { solution = JSON.parse(alert.playbook_solution); } catch(e) {}
                } else {
                    solution = alert.playbook_solution;
                }
            }
            
            let correctAction = solution.correct_action;

            // Smart fallback if no playbook solution exists (Must match startCrisis logic)
            if (!correctAction) {
                const titleLower = (alert.title || '').toLowerCase();
                const typeLower = (alert.alert_type || '').toLowerCase();
                const detailLower = (alert.details || '').toLowerCase(); // Use 'alert' here, not 'a'
                const sourceLower = (alert.source || '').toLowerCase();
                
                // 1. Phishing / Email -> Purge Inbox
                if (titleLower.includes('phish') || typeLower.includes('email') || sourceLower.includes('email') || detailLower.includes('sender')) {
                    correctAction = 'purge';
                } 
                // 2. Malware / Endpoint / Backdoor -> Isolate Host
                else if (
                    titleLower.includes('malware') || 
                    titleLower.includes('ransom') || 
                    titleLower.includes('backdoor') || 
                    titleLower.includes('trojan') || 
                    titleLower.includes('virus') || 
                    typeLower.includes('endpoint') || 
                    sourceLower.includes('edr') || 
                    sourceLower.includes('av') || 
                    detailLower.includes('process') || 
                    detailLower.includes('registry')
                ) {
                    correctAction = 'isolate';
                } 
                // 3. Identity / Login -> Lock Account
                else if (
                    titleLower.includes('brute') || 
                    titleLower.includes('login') || 
                    titleLower.includes('password') || 
                    titleLower.includes('credential') || 
                    titleLower.includes('user') || 
                    titleLower.includes('account') || 
                    typeLower.includes('identity') || 
                    sourceLower.includes('iam') || 
                    sourceLower.includes('ad')
                ) {
                    correctAction = 'lock';
                } 
                // 4. Network / C2 / Exfil -> Block IP
                else {
                    correctAction = 'block'; 
                }
            }
            const userAnswer = answers[alert.id];
            
            if (userAnswer === correctAction) {
                correctCount++;
            }
        }

        // Grading: 10 XP per correct + 100 bonus for perfect
        let xpEarned = correctCount * 10;
        const isPerfect = correctCount === totalCount && totalCount > 0;
        if (isPerfect) {
            xpEarned += 100;
        }

        // Update User XP
        if (xpEarned > 0) {
            await db.query("UPDATE user_xp SET total_xp = total_xp + ? WHERE user_id = ?", [xpEarned, userId]);
        }

        // Update operation progress as completed
        await db.query(
            `UPDATE user_operation_progress SET completed_at = NOW() WHERE user_id = ? AND operation_id = ? AND completed_at IS NULL`,
            [userId, operationId]
        );

        // Return result
        res.json({
            success: true,
            correctCount,
            totalCount,
            xpEarned,
            isPerfect,
            message: isPerfect ? 'Perfect Execution! Crisis Averted.' : `Crisis Contained. Score: ${correctCount}/${totalCount}`
        });

    } catch (error) {
        console.error('Crisis Submit Error:', error);
        res.status(500).json({ error: 'Failed to submit crisis results' });
    }
};

/**
 * Check if user can play Crisis Mode today
 */
exports.checkCrisisAvailability = async (req, res) => {
    try {
        const userId = Number(req.user.id);
        const alreadyPlayed = await hasPlayedToday(userId);
        
        res.json({
            available: !alreadyPlayed,
            message: alreadyPlayed ? 'Come back tomorrow!' : 'Crisis Mode available!'
        });
    } catch (error) {
        console.error('Crisis Check Error:', error);
        res.status(500).json({ error: 'Failed to check crisis availability' });
    }
};
