// Command Pattern Detector - Detects malicious command patterns (PowerShell, etc.)
// Browser Techniques Line 27: Command-pattern warnings
// Flag PowerShell/curl piping, base64 decode-exec, mshta/rundll, wscript/cscript patterns

import { BaseDetector } from '../base-detector.js';

export class CommandPatternDetector extends BaseDetector {
  constructor(config = {}) {
    super({
      name: 'command-pattern',
      category: 'social-engineering',
      version: '1.0.0',
      description: 'Detects malicious command patterns in clipboard/page content',
      weight: 4,
      severity: 'critical',
      ...config
    });
  }

  async detect(target, ruleRegistry) {
    const findings = [];
    const content = target.content || target.text || '';

    if (!content) {
      return this.createResult(false, [], 0);
    }

    const rules = ruleRegistry.getRules('social-engineering', 'command-pattern');

    if (!rules) {
      return this.createResult(false, [], 0);
    }

    // Normalize content for detection
    const normalized = content.toLowerCase();

    // 1. PowerShell command detection
    if (rules.powershellPatterns) {
      for (const pattern of rules.powershellPatterns) {
        const regex = new RegExp(pattern.pattern, 'gi');
        const matches = content.match(regex);

        if (matches) {
          findings.push(this.createFinding({
            pattern: 'powershell-command',
            matched: matches[0],
            description: pattern.description,
            severity: pattern.severity || 'critical',
            weight: pattern.weight || 4,
            metadata: {
              commandType: pattern.type,
              matchCount: matches.length,
              technique: 'powershell-execution'
            }
          }));
        }
      }
    }

    // 2. Base64 encoded command detection
    if (rules.base64Patterns) {
      for (const pattern of rules.base64Patterns) {
        if (this.testPattern(pattern.pattern, content)) {
          // Check if base64 string is suspiciously long (likely encoded command)
          const base64Matches = content.match(/[A-Za-z0-9+\/]{20,}={0,2}/g);

          if (base64Matches) {
            for (const b64 of base64Matches) {
              if (b64.length > 50) { // Suspiciously long base64
                findings.push(this.createFinding({
                  pattern: 'base64-command',
                  matched: b64.substring(0, 50) + '...',
                  description: pattern.description,
                  severity: pattern.severity || 'high',
                  weight: pattern.weight || 3,
                  metadata: {
                    base64Length: b64.length,
                    technique: 'base64-obfuscation'
                  }
                }));
                break; // Only report once per pattern
              }
            }
          }
        }
      }
    }

    // 3. Curl/wget piping detection
    if (rules.pipingPatterns) {
      for (const pattern of rules.pipingPatterns) {
        if (this.testPattern(pattern.pattern, content)) {
          const match = content.match(new RegExp(pattern.pattern, 'i'));

          findings.push(this.createFinding({
            pattern: 'pipe-to-shell',
            matched: match ? match[0] : pattern.pattern,
            description: pattern.description,
            severity: pattern.severity || 'critical',
            weight: pattern.weight || 5,
            metadata: {
              commandType: pattern.type,
              technique: 'download-execute'
            }
          }));
        }
      }
    }

    // 4. Windows LOLBins detection (mshta, rundll32, etc.)
    if (rules.lolbinPatterns) {
      for (const pattern of rules.lolbinPatterns) {
        if (this.testPattern(pattern.pattern, content)) {
          const match = content.match(new RegExp(pattern.pattern, 'i'));

          findings.push(this.createFinding({
            pattern: 'lolbin-abuse',
            matched: match ? match[0] : pattern.binary,
            description: pattern.description,
            severity: pattern.severity || 'critical',
            weight: pattern.weight || 4,
            metadata: {
              binary: pattern.binary,
              technique: 'lolbin-execution'
            }
          }));
        }
      }
    }

    // 5. Script execution detection (wscript, cscript)
    if (rules.scriptPatterns) {
      for (const pattern of rules.scriptPatterns) {
        if (this.testPattern(pattern.pattern, content)) {
          const match = content.match(new RegExp(pattern.pattern, 'i'));

          findings.push(this.createFinding({
            pattern: 'script-execution',
            matched: match ? match[0] : pattern.pattern,
            description: pattern.description,
            severity: pattern.severity || 'high',
            weight: pattern.weight || 3,
            metadata: {
              scriptEngine: pattern.engine,
              technique: 'script-execution'
            }
          }));
        }
      }
    }

    // 6. Obfuscation detection
    if (this.detectObfuscation(content)) {
      findings.push(this.createFinding({
        pattern: 'command-obfuscation',
        matched: 'Obfuscated command detected',
        description: 'Command appears to use obfuscation techniques',
        severity: 'high',
        weight: 3,
        metadata: {
          technique: 'obfuscation'
        }
      }));
    }

    // 7. Suspicious keyword combinations
    if (rules.suspiciousKeywords) {
      const keywordMatches = this.detectKeywordCombinations(
        content,
        rules.suspiciousKeywords
      );

      if (keywordMatches.length >= 2) { // Multiple suspicious keywords
        findings.push(this.createFinding({
          pattern: 'suspicious-keyword-combo',
          matched: keywordMatches.join(', '),
          description: 'Multiple suspicious command keywords detected',
          severity: 'medium',
          weight: 2,
          metadata: {
            keywords: keywordMatches,
            count: keywordMatches.length,
            technique: 'suspicious-commands'
          }
        }));
      }
    }

    const matched = findings.length > 0;
    const riskScore = findings.reduce((sum, f) => sum + (f.weight || 1), 0);

    return this.createResult(matched, findings, riskScore);
  }

  detectObfuscation(content) {
    // Check for common obfuscation patterns
    const obfuscationIndicators = [
      /\^/g,                          // PowerShell string concatenation with ^
      /`/g,                           // PowerShell backtick escaping
      /\$\{[^}]+\}/g,                // Variable expansion obfuscation
      /\[char\]/gi,                   // Character code obfuscation
      /-join/gi,                      // PowerShell join obfuscation
      /-f\s+['"][^'"]+['"]/gi,       // Format string obfuscation
      /\+\s*['"][a-z]['"][\s\+]/gi   // String concatenation obfuscation
    ];

    let obfuscationScore = 0;

    for (const indicator of obfuscationIndicators) {
      const matches = content.match(indicator);
      if (matches && matches.length > 2) {
        obfuscationScore++;
      }
    }

    return obfuscationScore >= 2; // Need at least 2 types of obfuscation
  }

  detectKeywordCombinations(content, keywords) {
    const normalized = content.toLowerCase();
    const matches = [];

    for (const keyword of keywords) {
      if (normalized.includes(keyword.toLowerCase())) {
        matches.push(keyword);
      }
    }

    return matches;
  }
}
