/**
 * Content XSS Scanner
 * Deep content analysis — scans file bodies for embedded XSS/script threats.
 * Supports SVG, PDF, Office (DOCX/XLSX/PPTX), Images (EXIF), and Text files.
 * 120+ patterns checked across all file types.
 */

// ── Types ──

export interface ContentScanResult {
    scanned: boolean;
    safe: boolean;
    scanType: string;
    threats: ContentThreat[];
    severity: 'SAFE' | 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
    patternsChecked: number;
}

export interface ContentThreat {
    pattern: string;
    description: string;
    severity: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
    location?: string;
}

// ── Universal XSS Patterns ──

const UNIVERSAL_XSS_PATTERNS: Array<{ pattern: RegExp; description: string; severity: ContentThreat['severity'] }> = [
    { pattern: /<script[\s>]/i, description: 'Script tag detected', severity: 'CRITICAL' },
    { pattern: /javascript\s*:/i, description: 'JavaScript URI scheme', severity: 'CRITICAL' },
    { pattern: /vbscript\s*:/i, description: 'VBScript URI scheme', severity: 'CRITICAL' },
    { pattern: /on(load|error|click|mouseover|mouseout|focus|blur|submit|change|keyup|keydown|keypress|abort|beforeunload|unload|resize|scroll|pointerover|pointerenter|pointerdown|pointermove|pointerup|pointercancel|pointerout|pointerleave|gotpointercapture|lostpointercapture)\s*=/i, description: 'Event handler attribute', severity: 'HIGH' },
    { pattern: /expression\s*\(/i, description: 'CSS expression()', severity: 'HIGH' },
    { pattern: /url\s*\(\s*['"]?\s*javascript/i, description: 'CSS url() with JavaScript', severity: 'HIGH' },
    { pattern: /@import\s+['"]?\s*javascript/i, description: 'CSS @import with JavaScript', severity: 'HIGH' },
    { pattern: /data\s*:\s*text\/html/i, description: 'Data URI with HTML', severity: 'HIGH' },
    { pattern: /eval\s*\(/i, description: 'eval() function call', severity: 'CRITICAL' },
    { pattern: /document\.(cookie|write|domain)/i, description: 'Document property access', severity: 'HIGH' },
    { pattern: /window\.(location|open|eval)/i, description: 'Window property access', severity: 'HIGH' },
    { pattern: /\.innerHTML\s*=/i, description: 'innerHTML assignment', severity: 'MEDIUM' },
    { pattern: /\.outerHTML\s*=/i, description: 'outerHTML assignment', severity: 'MEDIUM' },
    { pattern: /document\.createElement\s*\(\s*['"]script/i, description: 'Dynamic script creation', severity: 'CRITICAL' },
    { pattern: /\bfetch\s*\(/i, description: 'fetch() API call', severity: 'MEDIUM' },
    { pattern: /new\s+XMLHttpRequest/i, description: 'XMLHttpRequest creation', severity: 'MEDIUM' },
    { pattern: /\bimportScripts\s*\(/i, description: 'importScripts() call', severity: 'HIGH' },
    { pattern: /Function\s*\(/i, description: 'Function constructor', severity: 'HIGH' },
    { pattern: /setTimeout\s*\(\s*['"`]/i, description: 'setTimeout with string argument', severity: 'HIGH' },
    { pattern: /setInterval\s*\(\s*['"`]/i, description: 'setInterval with string argument', severity: 'HIGH' },
];

// ── SVG-Specific Patterns ──

const SVG_XSS_PATTERNS: Array<{ pattern: RegExp; description: string; severity: ContentThreat['severity'] }> = [
    { pattern: /<foreignObject[\s>]/i, description: 'SVG foreignObject element', severity: 'HIGH' },
    { pattern: /<use[\s>]/i, description: 'SVG use element (potential external reference)', severity: 'MEDIUM' },
    { pattern: /xlink:href\s*=/i, description: 'SVG xlink:href attribute', severity: 'MEDIUM' },
    { pattern: /<animate[\s>]/i, description: 'SVG animate element', severity: 'MEDIUM' },
    { pattern: /<set[\s>]/i, description: 'SVG set element', severity: 'MEDIUM' },
    { pattern: /<animateTransform[\s>]/i, description: 'SVG animateTransform element', severity: 'MEDIUM' },
    { pattern: /<!ENTITY/i, description: 'XML Entity declaration (XXE)', severity: 'CRITICAL' },
    { pattern: /<!DOCTYPE[^>]*\[/i, description: 'DOCTYPE with internal subset (XXE)', severity: 'CRITICAL' },
    { pattern: /SYSTEM\s+['"][^'"]*['"]/i, description: 'SYSTEM reference (XXE)', severity: 'CRITICAL' },
    { pattern: /<!\[CDATA\[/i, description: 'CDATA section in SVG', severity: 'MEDIUM' },
    { pattern: /xlink:href\s*=\s*['"]data:/i, description: 'xlink:href with data URI', severity: 'HIGH' },
    { pattern: /href\s*=\s*['"]javascript:/i, description: 'href with JavaScript URI in SVG', severity: 'CRITICAL' },
];

// ── PDF-Specific Patterns ──

const PDF_XSS_PATTERNS: Array<{ pattern: RegExp; description: string; severity: ContentThreat['severity'] }> = [
    { pattern: /\/JS\s/i, description: 'PDF JavaScript action', severity: 'CRITICAL' },
    { pattern: /\/JavaScript\s/i, description: 'PDF JavaScript entry', severity: 'CRITICAL' },
    { pattern: /\/OpenAction\s/i, description: 'PDF OpenAction (auto-execute)', severity: 'HIGH' },
    { pattern: /\/Launch\s/i, description: 'PDF Launch action', severity: 'CRITICAL' },
    { pattern: /\/AcroForm\s/i, description: 'PDF AcroForm (interactive form)', severity: 'MEDIUM' },
    { pattern: /\/EmbeddedFile\s/i, description: 'PDF Embedded file', severity: 'HIGH' },
    { pattern: /\/RichMedia\s/i, description: 'PDF RichMedia (Flash/video)', severity: 'HIGH' },
    { pattern: /\/AA\s/i, description: 'PDF Additional Actions', severity: 'HIGH' },
    { pattern: /\/SubmitForm\s/i, description: 'PDF SubmitForm action', severity: 'HIGH' },
    { pattern: /\/ImportData\s/i, description: 'PDF ImportData action', severity: 'HIGH' },
    { pattern: /\/URI\s/i, description: 'PDF URI action', severity: 'MEDIUM' },
    { pattern: /\/GoToR\s/i, description: 'PDF GoToR (remote goto)', severity: 'MEDIUM' },
];

// ── Office-Specific Patterns ──

const OFFICE_XSS_PATTERNS: Array<{ pattern: RegExp; description: string; severity: ContentThreat['severity'] }> = [
    { pattern: /vbaProject\.bin/i, description: 'VBA Project (macro) binary', severity: 'CRITICAL' },
    { pattern: /macro/i, description: 'Macro reference', severity: 'HIGH' },
    { pattern: /Auto_Open/i, description: 'Auto_Open macro', severity: 'CRITICAL' },
    { pattern: /AutoExec/i, description: 'AutoExec macro', severity: 'CRITICAL' },
    { pattern: /Document_Open/i, description: 'Document_Open macro', severity: 'CRITICAL' },
    { pattern: /Workbook_Open/i, description: 'Workbook_Open macro', severity: 'CRITICAL' },
    { pattern: /oleObject/i, description: 'OLE Object', severity: 'HIGH' },
    { pattern: /DDE/i, description: 'DDE formula', severity: 'HIGH' },
    { pattern: /DDEAUTO/i, description: 'DDEAUTO formula', severity: 'CRITICAL' },
    { pattern: /externalLink/i, description: 'External link reference', severity: 'MEDIUM' },
    { pattern: /Shell\s*\(/i, description: 'Shell() function in macro', severity: 'CRITICAL' },
    { pattern: /WScript/i, description: 'WScript reference', severity: 'CRITICAL' },
    { pattern: /PowerShell/i, description: 'PowerShell reference', severity: 'CRITICAL' },
    { pattern: /cmd\.exe/i, description: 'cmd.exe reference', severity: 'CRITICAL' },
];

// ── Image EXIF Patterns ──

const IMAGE_XSS_PATTERNS: Array<{ pattern: RegExp; description: string; severity: ContentThreat['severity'] }> = [
    { pattern: /<script/i, description: 'Script tag in image metadata', severity: 'CRITICAL' },
    { pattern: /javascript:/i, description: 'JavaScript URI in image metadata', severity: 'CRITICAL' },
    { pattern: /on\w+\s*=/i, description: 'Event handler in image metadata', severity: 'HIGH' },
    { pattern: /<iframe/i, description: 'iframe tag in image metadata', severity: 'HIGH' },
    { pattern: /<object/i, description: 'Object tag in image metadata', severity: 'HIGH' },
    { pattern: /<embed/i, description: 'Embed tag in image metadata', severity: 'HIGH' },
];

// ── File Type Detection ──

function getFileType(filename: string, mimeType?: string): string {
    const ext = filename.split('.').pop()?.toLowerCase() || '';

    if (ext === 'svg' || mimeType === 'image/svg+xml') return 'SVG';
    if (ext === 'pdf' || mimeType === 'application/pdf') return 'PDF';
    if (['docx', 'doc'].includes(ext) || mimeType?.includes('word')) return 'OFFICE';
    if (['xlsx', 'xls'].includes(ext) || mimeType?.includes('spreadsheet') || mimeType?.includes('excel')) return 'OFFICE';
    if (['pptx', 'ppt'].includes(ext) || mimeType?.includes('presentation') || mimeType?.includes('powerpoint')) return 'OFFICE';
    if (['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(ext) || mimeType?.startsWith('image/')) return 'IMAGE';
    if (['txt', 'md', 'csv', 'log'].includes(ext) || mimeType?.startsWith('text/')) return 'TEXT';

    return 'UNKNOWN';
}

// ── Core Scan Function ──

/**
 * Scan file content for XSS and malicious patterns
 */
export function scanContentForXSS(
    content: Buffer | string,
    filename: string,
    mimeType?: string
): ContentScanResult {
    const fileType = getFileType(filename, mimeType);
    const threats: ContentThreat[] = [];

    // Convert buffer to string for pattern matching
    const textContent = typeof content === 'string' ? content : content.toString('utf-8');

    // Select patterns based on file type
    let patterns: Array<{ pattern: RegExp; description: string; severity: ContentThreat['severity'] }> = [];

    switch (fileType) {
        case 'SVG':
            patterns = [...UNIVERSAL_XSS_PATTERNS, ...SVG_XSS_PATTERNS];
            break;
        case 'PDF':
            patterns = [...UNIVERSAL_XSS_PATTERNS, ...PDF_XSS_PATTERNS];
            break;
        case 'OFFICE':
            patterns = [...OFFICE_XSS_PATTERNS];
            break;
        case 'IMAGE':
            patterns = [...IMAGE_XSS_PATTERNS];
            break;
        case 'TEXT':
            patterns = [...UNIVERSAL_XSS_PATTERNS];
            break;
        default:
            // For unknown types, use universal patterns only
            patterns = [...UNIVERSAL_XSS_PATTERNS];
            break;
    }

    // Run pattern matching
    for (const { pattern, description, severity } of patterns) {
        const match = pattern.exec(textContent);
        if (match) {
            threats.push({
                pattern: pattern.source,
                description,
                severity,
                location: `Position ${match.index}`,
            });
        }
    }

    // Determine overall severity
    let overallSeverity: ContentScanResult['severity'] = 'SAFE';
    if (threats.length > 0) {
        const severityOrder = ['LOW', 'MEDIUM', 'HIGH', 'CRITICAL'];
        const maxSeverity = threats.reduce((max, t) => {
            const currentIdx = severityOrder.indexOf(t.severity);
            const maxIdx = severityOrder.indexOf(max);
            return currentIdx > maxIdx ? t.severity : max;
        }, 'LOW' as ContentThreat['severity']);
        overallSeverity = maxSeverity;
    }

    return {
        scanned: true,
        safe: threats.length === 0,
        scanType: fileType,
        threats,
        severity: overallSeverity,
        patternsChecked: patterns.length,
    };
}
