/**
 * Migration Script: Fix Missing Payload Artifacts
 * 
 * This script re-processes existing alerts to add missing payload artifacts
 * (SQL injection, XSS, command injection) to their playbook_solution.
 * 
 * Usage:
 *   node src/scripts/fix_missing_payloads.js           # Run migration
 *   node src/scripts/fix_missing_payloads.js --dry-run # Preview without updating
 */

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

// ============= ATTACK PATTERN DETECTION =============

// SQL Injection
const SQL_PATTERNS = [
    /' OR '/i, /' AND '/i, /--\s*$/m, /UNION\s+SELECT/i,
    /'\s*=\s*'/i, /1\s*=\s*1/i, /DROP\s+TABLE/i, /'\s*OR\s+'\d+'\s*=\s*'\d+/i,
    /WAITFOR\s+DELAY/i, /xp_cmdshell/i, /EXEC\s+\(/i
];

// XSS
const XSS_PATTERNS = [
    /<script/i, /javascript:/i, /onerror\s*=/i, /onload\s*=/i,
    /eval\s*\(/i, /document\.cookie/i, /alert\s*\(/i, /fromCharCode/i
];

// Basic Command Injection (Shell)
const CMD_PATTERNS = [
    /\$\(/, /`[^`]+`/, /;\s*\w+/, /\|\s*\w+/, /&&\s*\w+/,
    /\bexec\s*\(/i, /\bsystem\s*\(/i, /\/bin\/bash/i, /\/bin\/sh/i
];

// PowerShell (Critical for SOC training)
const POWERSHELL_PATTERNS = [
    { pattern: /powershell.*-enc\s+[A-Za-z0-9+\/=]{20,}/i, subtype: 'encoded_powershell' },
    { pattern: /-encodedcommand\s+[A-Za-z0-9+\/=]+/i, subtype: 'encoded_powershell' },
    { pattern: /Invoke-Expression/i, subtype: 'iex_execution' },
    { pattern: /IEX\s*\(/i, subtype: 'iex_execution' },
    { pattern: /Invoke-WebRequest/i, subtype: 'download_cradle' },
    { pattern: /DownloadString\s*\(/i, subtype: 'download_cradle' },
    { pattern: /New-Object.*Net\.WebClient/i, subtype: 'download_cradle' },
    { pattern: /Invoke-Mimikatz/i, subtype: 'credential_theft' },
    { pattern: /\[System\.Convert\]::FromBase64/i, subtype: 'base64_decode' },
    { pattern: /-nop\s+-w\s+hidden/i, subtype: 'hidden_execution' },
    { pattern: /bypass.*-executionpolicy/i, subtype: 'bypass_policy' },
    { pattern: /Set-ExecutionPolicy.*Bypass/i, subtype: 'bypass_policy' },
    { pattern: /\$env:.*\+.*\$env:/i, subtype: 'env_obfuscation' }
];

// LOLBins (Living Off the Land Binaries)
const LOLBIN_PATTERNS = [
    { pattern: /certutil.*-urlcache/i, subtype: 'certutil_download' },
    { pattern: /certutil.*-decode/i, subtype: 'certutil_decode' },
    { pattern: /mshta\s+/i, subtype: 'mshta_execution' },
    { pattern: /regsvr32.*\/s.*\/u.*\/i/i, subtype: 'regsvr32_proxy' },
    { pattern: /rundll32.*javascript/i, subtype: 'rundll32_abuse' },
    { pattern: /wmic.*process.*call.*create/i, subtype: 'wmic_execution' },
    { pattern: /bitsadmin.*\/transfer/i, subtype: 'bitsadmin_download' },
    { pattern: /cscript.*\/e:jscript/i, subtype: 'script_host' },
    { pattern: /wscript.*\/e:jscript/i, subtype: 'script_host' },
    { pattern: /msiexec.*\/q.*http/i, subtype: 'msiexec_download' }
];

/**
 * Check if a string contains attack patterns
 */
const detectAttackType = (value) => {
    if (!value || typeof value !== 'string') return null;
    
    // Check SQL injection
    for (const pattern of SQL_PATTERNS) {
        if (pattern.test(value)) return { type: 'sql_injection', subtype: 'sql_injection' };
    }
    
    // Check XSS
    for (const pattern of XSS_PATTERNS) {
        if (pattern.test(value)) return { type: 'xss', subtype: 'xss' };
    }
    
    // Check PowerShell (detailed subtypes)
    for (const { pattern, subtype } of POWERSHELL_PATTERNS) {
        if (pattern.test(value)) return { type: 'powershell', subtype };
    }
    
    // Check LOLBins (detailed subtypes)
    for (const { pattern, subtype } of LOLBIN_PATTERNS) {
        if (pattern.test(value)) return { type: 'lolbin', subtype };
    }
    
    // Check basic command injection
    for (const pattern of CMD_PATTERNS) {
        if (pattern.test(value)) return { type: 'command_injection', subtype: 'shell_injection' };
    }
    
    return null;
};

/**
 * Extract payload values from raw_log
 */
const extractPayloads = (rawLog) => {
    if (!rawLog) return [];
    
    const payloads = [];
    const payloadFields = ['request_body', 'payload', 'body', 'query_string', 'parameters', 'input', 'data'];
    const commandFields = ['command_line', 'command', 'cmd', 'process_command', 'executed_command', 'process'];
    
    // Check explicit payload fields
    [...payloadFields, ...commandFields].forEach(field => {
        if (rawLog[field] && typeof rawLog[field] === 'string') {
            const detection = detectAttackType(rawLog[field]);
            if (detection) {
                payloads.push({
                    value: rawLog[field],
                    type: (detection.type === 'command_injection' || detection.type === 'powershell' || detection.type === 'lolbin') ? 'command' : 'payload',
                    attackType: detection.type,
                    subtype: detection.subtype
                });
            }
        }
    });
    
    // Also check all string values for attack patterns
    Object.entries(rawLog).forEach(([key, val]) => {
        if (typeof val === 'string' && !payloadFields.includes(key) && !commandFields.includes(key)) {
            const detection = detectAttackType(val);
            if (detection && !payloads.some(p => p.value === val)) {
                payloads.push({
                    value: val,
                    type: (detection.type === 'command_injection' || detection.type === 'powershell' || detection.type === 'lolbin') ? 'command' : 'payload',
                    attackType: detection.type,
                    subtype: detection.subtype,
                    sourceField: key
                });
            }
        }
    });
    
    return payloads;
};

/**
 * Check if playbook already has this payload artifact
 */
const hasPayloadArtifact = (artifacts, payloadValue) => {
    return artifacts.some(a => 
        (a.type === 'payload' || a.type === 'command') && 
        a.value === payloadValue
    );
};

/**
 * Add missing payload artifacts to playbook
 */
const addPayloadArtifacts = (playbook, payloads) => {
    if (!playbook.artifacts) {
        playbook.artifacts = [];
    }
    
    let added = 0;
    payloads.forEach((payload, idx) => {
        if (!hasPayloadArtifact(playbook.artifacts, payload.value)) {
            const newArtifact = {
                id: `payload_${Date.now()}_${idx}`,
                type: payload.type,
                value: payload.value,
                is_critical: true,
                osint_result: {
                    source: 'Pattern Analysis',
                    verdict: 'malicious',
                    details: getPayloadDetails(payload.attackType, payload.subtype, payload.value)
                }
            };
            playbook.artifacts.push(newArtifact);
            added++;
        }
    });
    
    return added;
};

/**
 * Generate appropriate OSINT details for payload type
 */
const getPayloadDetails = (attackType, subtype, value) => {
    // PowerShell subtypes
    const powershellDetails = {
        'encoded_powershell': 'Base64-encoded PowerShell command detected. Attackers commonly encode commands to evade detection. Decode and analyze the payload.',
        'iex_execution': 'Invoke-Expression (IEX) detected. This cmdlet executes strings as commands and is commonly used in fileless malware.',
        'download_cradle': 'PowerShell download cradle detected. Attacker attempting to download and execute remote payload.',
        'credential_theft': 'Invoke-Mimikatz detected. Credential harvesting tool attempting to extract passwords from memory.',
        'base64_decode': 'Base64 decoding in PowerShell detected. Commonly used to decode embedded malicious payloads.',
        'hidden_execution': 'Hidden window execution detected. PowerShell running with hidden window to avoid user detection.',
        'bypass_policy': 'Execution policy bypass detected. Attacker attempting to circumvent PowerShell security controls.',
        'env_obfuscation': 'Environment variable obfuscation detected. Technique used to evade signature-based detection.'
    };
    
    // LOLBins subtypes
    const lolbinDetails = {
        'certutil_download': 'Certutil download detected. Windows utility being abused to download files from the internet.',
        'certutil_decode': 'Certutil decode detected. Base64 decoding via Windows utility to extract hidden payload.',
        'mshta_execution': 'MSHTA execution detected. HTML Application host being used to execute malicious scripts.',
        'regsvr32_proxy': 'Regsvr32 proxy execution detected. COM scriptlet being loaded to bypass application whitelisting.',
        'rundll32_abuse': 'Rundll32 JavaScript execution detected. Windows utility being abused for script execution.',
        'wmic_execution': 'WMIC process creation detected. WMI being used for lateral movement or persistence.',
        'bitsadmin_download': 'BITS transfer detected. Background Intelligent Transfer Service abused for file download.',
        'script_host': 'Windows Script Host execution detected. Cscript/Wscript being used to run malicious scripts.',
        'msiexec_download': 'MSIexec remote install detected. Windows Installer being abused to download and execute payload.'
    };
    
    // Check for specific subtypes first
    if (subtype && powershellDetails[subtype]) {
        return powershellDetails[subtype];
    }
    if (subtype && lolbinDetails[subtype]) {
        return lolbinDetails[subtype];
    }
    
    // Fall back to general type descriptions
    switch (attackType) {
        case 'sql_injection':
            return 'SQL injection attempt detected. Pattern matches known injection techniques attempting to bypass authentication or extract data.';
        case 'xss':
            return 'Cross-Site Scripting (XSS) payload detected. Malicious script injection attempt that could steal session cookies or redirect users.';
        case 'command_injection':
            return 'Command injection attempt detected. Attacker attempting to execute system commands on the target server.';
        case 'powershell':
            return 'Suspicious PowerShell activity detected. Malicious cmdlet or obfuscation technique identified.';
        case 'lolbin':
            return 'Living-off-the-Land Binary (LOLBin) abuse detected. Legitimate Windows tool being used for malicious purposes.';
        default:
            return 'Malicious payload detected in request. Analyze for indicators of compromise.';
    }
};

/**
 * Main migration function
 */
const runMigration = async (dryRun = false) => {
    console.log(`\n🔧 Payload Artifact Migration ${dryRun ? '(DRY RUN)' : ''}`);
    console.log('='.repeat(50));
    
    try {
        // Fetch all alerts with playbook_solution
        const result = await db.query(`
            SELECT id, title, raw_log, playbook_solution 
            FROM alerts 
            WHERE playbook_solution IS NOT NULL
        `);
        
        const alerts = result.rows;
        console.log(`📋 Found ${alerts.length} alerts with playbook_solution\n`);
        
        let updated = 0;
        let alreadyComplete = 0;
        let noPayloadsFound = 0;
        let errors = 0;
        
        for (const alert of alerts) {
            try {
                // Parse JSON fields
                let rawLog = alert.raw_log;
                let playbook = alert.playbook_solution;
                
                if (typeof rawLog === 'string') {
                    try { rawLog = JSON.parse(rawLog); } catch (e) { rawLog = null; }
                }
                if (typeof playbook === 'string') {
                    try { playbook = JSON.parse(playbook); } catch (e) { playbook = null; }
                }
                
                if (!rawLog || !playbook) {
                    continue;
                }
                
                // Extract payloads from raw_log
                const payloads = extractPayloads(rawLog);
                
                if (payloads.length === 0) {
                    noPayloadsFound++;
                    continue;
                }
                
                // Check if already has payload artifacts
                const existingPayloadArtifacts = (playbook.artifacts || []).filter(
                    a => a.type === 'payload' || a.type === 'command'
                );
                
                if (existingPayloadArtifacts.length >= payloads.length) {
                    alreadyComplete++;
                    continue;
                }
                
                // Add missing payload artifacts
                const addedCount = addPayloadArtifacts(playbook, payloads);
                
                if (addedCount > 0) {
                    console.log(`✅ Alert #${alert.id}: "${alert.title.substring(0, 40)}..."`);
                    console.log(`   Added ${addedCount} payload artifact(s): ${payloads.map(p => p.attackType).join(', ')}`);
                    
                    if (!dryRun) {
                        // Update database
                        await db.query(
                            'UPDATE alerts SET playbook_solution = ? WHERE id = ?',
                            [JSON.stringify(playbook), alert.id]
                        );
                    }
                    updated++;
                }
                
            } catch (err) {
                console.error(`❌ Error processing alert #${alert.id}:`, err.message);
                errors++;
            }
        }
        
        console.log('\n' + '='.repeat(50));
        console.log('📊 Migration Summary:');
        console.log(`   ✅ Updated: ${updated} alerts`);
        console.log(`   ⏭️  Already complete: ${alreadyComplete} alerts`);
        console.log(`   🔍 No payloads found: ${noPayloadsFound} alerts`);
        console.log(`   ❌ Errors: ${errors}`);
        
        if (dryRun) {
            console.log('\n⚠️  DRY RUN - No changes were saved. Run without --dry-run to apply.');
        } else {
            console.log('\n✅ Migration complete!');
        }
        
    } catch (err) {
        console.error('Migration failed:', err);
        process.exit(1);
    }
    
    process.exit(0);
};

// Parse command line arguments
const args = process.argv.slice(2);
const dryRun = args.includes('--dry-run');

runMigration(dryRun);
