// Clipboard Poisoning Detector - Detects clipboard manipulation attacks
// Browser Techniques Line 231: Clipboard poisoning (address swap)
// Replace copied crypto addresses during copy/paste flows

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

export class ClipboardPoisoningDetector extends BaseDetector {
  constructor(config = {}) {
    super({
      name: 'clipboard-poisoning',
      category: 'data-theft',
      version: '1.0.0',
      description: 'Detects clipboard poisoning and address swap attacks',
      weight: 3,
      severity: 'high',
      ...config
    });
  }

  async detect(target, ruleRegistry) {
    const findings = [];

    // This detector requires clipboard event monitoring data
    const clipboardWrites = target.clipboardWrites || [];
    const copyEvents = target.copyEvents || [];
    const permissions = target.permissions || {};

    if (clipboardWrites.length === 0 && copyEvents.length === 0) {
      return this.createResult(false, [], 0);
    }

    const rules = ruleRegistry.getRules('data-theft', 'clipboard-poisoning');

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

    // 1. Detect crypto address swapping
    for (const write of clipboardWrites) {
      const addressSwap = this.detectCryptoAddressSwap(
        write.originalText,
        write.newText,
        rules
      );

      if (addressSwap.detected) {
        findings.push(this.createFinding({
          pattern: 'crypto-address-swap',
          matched: `${addressSwap.cryptoType} address swap detected`,
          description: `Clipboard poisoning: ${addressSwap.cryptoType} address replaced`,
          severity: 'critical',
          weight: 5,
          metadata: {
            cryptoType: addressSwap.cryptoType,
            originalAddress: write.originalText,
            maliciousAddress: write.newText,
            technique: 'crypto-clipboard-hijacking'
          }
        }));
      }
    }

    // 2. Detect copy event manipulation (pastejacking)
    for (const copyEvent of copyEvents) {
      if (copyEvent.userSelected && copyEvent.pageModified) {
        const isDifferent = copyEvent.userSelected !== copyEvent.pageModified;

        if (isDifferent) {
          const severity = this.assessPastejackingSeverity(
            copyEvent.userSelected,
            copyEvent.pageModified,
            rules
          );

          findings.push(this.createFinding({
            pattern: 'pastejacking',
            matched: 'User selection modified during copy',
            description: 'Copy event hijacked - pasted content will differ from selection',
            severity: severity,
            weight: severity === 'critical' ? 5 : 3,
            metadata: {
              userSelected: copyEvent.userSelected,
              pageModified: copyEvent.pageModified,
              technique: 'pastejacking'
            }
          }));
        }
      }
    }

    // 3. Detect unauthorized clipboard writes
    if (clipboardWrites.length > 0 && !permissions.hasClipboardPermission) {
      findings.push(this.createFinding({
        pattern: 'unauthorized-clipboard-write',
        matched: `${clipboardWrites.length} unauthorized writes`,
        description: 'Clipboard modified without explicit permission',
        severity: 'high',
        weight: 4,
        metadata: {
          writeCount: clipboardWrites.length,
          technique: 'permission-bypass'
        }
      }));
    }

    // 4. Detect excessive clipboard monitoring
    if (target.clipboardReadCount > (rules.excessiveReadThreshold || 10)) {
      findings.push(this.createFinding({
        pattern: 'excessive-clipboard-monitoring',
        matched: `${target.clipboardReadCount} clipboard reads`,
        description: 'Excessive clipboard monitoring (potential data theft)',
        severity: 'medium',
        weight: 2,
        metadata: {
          readCount: target.clipboardReadCount,
          technique: 'clipboard-snooping'
        }
      }));
    }

    // 5. Detect sensitive data in clipboard writes
    for (const write of clipboardWrites) {
      const sensitiveData = this.detectSensitiveData(write.newText, rules);

      if (sensitiveData.detected) {
        findings.push(this.createFinding({
          pattern: 'sensitive-data-clipboard',
          matched: sensitiveData.type,
          description: `Sensitive data written to clipboard: ${sensitiveData.type}`,
          severity: 'medium',
          weight: 2,
          metadata: {
            dataType: sensitiveData.type,
            technique: 'credential-harvesting'
          }
        }));
      }
    }

    // 6. Detect command injection in clipboard
    for (const copyEvent of copyEvents) {
      if (copyEvent.pageModified) {
        const hasCommandInjection = this.detectCommandInjection(
          copyEvent.pageModified,
          rules
        );

        if (hasCommandInjection) {
          findings.push(this.createFinding({
            pattern: 'clipboard-command-injection',
            matched: copyEvent.pageModified.substring(0, 50),
            description: 'Malicious command injected into clipboard',
            severity: 'critical',
            weight: 5,
            metadata: {
              command: copyEvent.pageModified,
              technique: 'clipboard-command-injection'
            }
          }));
        }
      }
    }

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

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

  detectCryptoAddressSwap(original, modified, rules) {
    if (!original || !modified || original === modified) {
      return { detected: false };
    }

    const cryptoPatterns = rules.cryptoAddressPatterns || {
      bitcoin: /^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$/,
      ethereum: /^0x[a-fA-F0-9]{40}$/,
      litecoin: /^[LM3][a-km-zA-HJ-NP-Z1-9]{26,33}$/,
      dogecoin: /^D{1}[5-9A-HJ-NP-U]{1}[1-9A-HJ-NP-Za-km-z]{32}$/,
      monero: /^4[0-9AB][1-9A-HJ-NP-Za-km-z]{93}$/
    };

    for (const [cryptoType, pattern] of Object.entries(cryptoPatterns)) {
      if (pattern.test(original) && pattern.test(modified)) {
        return {
          detected: true,
          cryptoType
        };
      }
    }

    return { detected: false };
  }

  assessPastejackingSeverity(userSelected, pageModified, rules) {
    const dangerousPatterns = rules.dangerousPatterns || [
      /curl.*\|.*sh/i,
      /wget.*\|.*sh/i,
      /sudo/i,
      /rm\s+-rf/i,
      /chmod/i,
      /eval/i,
      /exec/i,
      /powershell/i,
      /cmd\.exe/i
    ];

    for (const pattern of dangerousPatterns) {
      if (pattern.test(pageModified)) {
        return 'critical';
      }
    }

    return 'high';
  }

  detectSensitiveData(text, rules) {
    const sensitivePatterns = rules.sensitivePatterns || [
      { pattern: /\b\d{16}\b/, type: 'credit-card-number' },
      { pattern: /\b\d{3}-\d{2}-\d{4}\b/, type: 'ssn' },
      { pattern: /password/i, type: 'password-text' },
      { pattern: /api[_-]?key/i, type: 'api-key' },
      { pattern: /bearer\s+[a-zA-Z0-9_-]+/i, type: 'bearer-token' }
    ];

    for (const { pattern, type } of sensitivePatterns) {
      if (pattern.test(text)) {
        return { detected: true, type };
      }
    }

    return { detected: false };
  }

  detectCommandInjection(text, rules) {
    const commandPatterns = rules.commandPatterns || [
      /curl.*\|.*bash/i,
      /wget.*\|.*sh/i,
      /;.*rm\s+-rf/i,
      /&&.*rm\s+-rf/i,
      /sudo\s+/i,
      /chmod\s+\+x/i,
      /eval\s*\(/i,
      /exec\s*\(/i,
      /powershell.*-e[nc]*/i,
      /cmd\.exe.*\/c/i
    ];

    return commandPatterns.some(pattern => pattern.test(text));
  }
}
