// WASM Mining Detector - Detects WebAssembly cryptocurrency mining
// Browser Techniques Line 76: WASM cryptomining
// Mining loops in WASM to reduce detection by JS-only heuristics

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

export class WasmMiningDetector extends BaseDetector {
  constructor(config = {}) {
    super({
      name: 'wasm-mining',
      category: 'code-injection',
      version: '1.0.0',
      description: 'Detects WebAssembly cryptocurrency mining',
      weight: 3,
      severity: 'high',
      ...config
    });
  }

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

    // This detector requires script/WASM data from content script
    const wasmModules = target.wasmModules || [];
    const scripts = target.scripts || [];
    const webWorkers = target.webWorkers || [];
    const networkConnections = target.networkConnections || [];
    const cpuUsage = target.cpuUsage;

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

    const rules = ruleRegistry.getRules('code-injection', 'wasm-mining');

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

    // 1. Detect known mining library signatures
    for (const script of scripts) {
      const miningLib = this.detectMiningLibrary(script, rules);

      if (miningLib) {
        findings.push(this.createFinding({
          pattern: 'known-mining-library',
          matched: miningLib.name,
          description: `Known cryptocurrency mining library detected: ${miningLib.name}`,
          severity: 'critical',
          weight: 5,
          metadata: {
            library: miningLib.name,
            scriptSrc: script.src,
            technique: 'wasm-mining-library'
          }
        }));
      }
    }

    // 2. Detect WASM modules with mining patterns
    for (const wasmModule of wasmModules) {
      if (this.isSuspiciousWasmModule(wasmModule, rules)) {
        findings.push(this.createFinding({
          pattern: 'suspicious-wasm-module',
          matched: wasmModule.src || 'inline WASM',
          description: 'WebAssembly module with cryptocurrency mining patterns',
          severity: 'high',
          weight: 4,
          metadata: {
            wasmSrc: wasmModule.src,
            size: wasmModule.size,
            technique: 'wasm-mining-module'
          }
        }));
      }
    }

    // 3. Detect crypto mining pool connections
    for (const connection of networkConnections) {
      const miningPool = this.isMiningPoolConnection(connection, rules);

      if (miningPool) {
        findings.push(this.createFinding({
          pattern: 'mining-pool-connection',
          matched: connection.url,
          description: `Connection to cryptocurrency mining pool: ${miningPool.pool}`,
          severity: 'critical',
          weight: 5,
          metadata: {
            poolDomain: connection.url,
            poolName: miningPool.pool,
            protocol: connection.protocol,
            technique: 'wasm-mining-pool'
          }
        }));
      }
    }

    // 4. Detect WebWorker + WASM combination (common mining pattern)
    if (webWorkers.length > 0 && wasmModules.length > 0) {
      const workersUsingWasm = webWorkers.filter(worker =>
        worker.usesWasm || wasmModules.some(wasm => worker.modules?.includes(wasm.src))
      );

      if (workersUsingWasm.length > 0) {
        findings.push(this.createFinding({
          pattern: 'webworker-wasm-mining',
          matched: `${workersUsingWasm.length} workers using WASM`,
          description: 'WebWorkers using WebAssembly (common mining pattern)',
          severity: 'high',
          weight: 4,
          metadata: {
            workerCount: workersUsingWasm.length,
            technique: 'wasm-mining-worker'
          }
        }));
      }
    }

    // 5. Detect high CPU usage
    if (cpuUsage && cpuUsage > (rules.suspiciousCpuThreshold || 70)) {
      const hasWasmOrWorkers = wasmModules.length > 0 || webWorkers.length > 0;

      if (hasWasmOrWorkers) {
        findings.push(this.createFinding({
          pattern: 'high-cpu-with-wasm',
          matched: `${cpuUsage}% CPU usage`,
          description: 'High CPU usage with WASM/WebWorkers present',
          severity: 'high',
          weight: 4,
          metadata: {
            cpuUsage,
            hasWasm: wasmModules.length > 0,
            hasWorkers: webWorkers.length > 0,
            technique: 'wasm-mining-cpu'
          }
        }));
      }
    }

    // 6. Detect mining-related function names in scripts
    for (const script of scripts) {
      if (script.content) {
        const miningFunctions = this.detectMiningFunctions(script.content, rules);

        if (miningFunctions.length > 0) {
          findings.push(this.createFinding({
            pattern: 'mining-function-names',
            matched: miningFunctions.join(', '),
            description: 'Script contains cryptocurrency mining function names',
            severity: 'high',
            weight: 3,
            metadata: {
              functions: miningFunctions,
              scriptSrc: script.src,
              technique: 'wasm-mining-functions'
            }
          }));
        }
      }
    }

    // 7. Detect WebSocket connections to mining pools
    const wsMiningConnections = networkConnections.filter(conn =>
      conn.protocol === 'ws' || conn.protocol === 'wss'
    ).filter(conn => this.isMiningPoolConnection(conn, rules));

    if (wsMiningConnections.length > 0) {
      findings.push(this.createFinding({
        pattern: 'websocket-mining-connection',
        matched: `${wsMiningConnections.length} WebSocket mining connections`,
        description: 'WebSocket connections to cryptocurrency mining pools',
        severity: 'critical',
        weight: 5,
        metadata: {
          connections: wsMiningConnections.map(c => c.url),
          technique: 'wasm-mining-websocket'
        }
      }));
    }

    // 8. Detect obfuscated WASM loaders
    for (const script of scripts) {
      if (script.content && script.obfuscationScore > 2) {
        const loadsWasm = /WebAssembly\.(instantiate|compile)/i.test(script.content);

        if (loadsWasm) {
          findings.push(this.createFinding({
            pattern: 'obfuscated-wasm-loader',
            matched: script.src || 'inline script',
            description: 'Obfuscated script loading WebAssembly modules',
            severity: 'high',
            weight: 4,
            metadata: {
              scriptSrc: script.src,
              obfuscationScore: script.obfuscationScore,
              technique: 'wasm-mining-obfuscation'
            }
          }));
        }
      }
    }

    // 9. Detect multiple WASM modules (unusual)
    const multiWasmThreshold = rules.multipleWasmThreshold || 2;

    if (wasmModules.length >= multiWasmThreshold) {
      findings.push(this.createFinding({
        pattern: 'multiple-wasm-modules',
        matched: `${wasmModules.length} WASM modules`,
        description: 'Multiple WebAssembly modules loaded (unusual)',
        severity: 'medium',
        weight: 2,
        metadata: {
          moduleCount: wasmModules.length,
          technique: 'wasm-mining-multiple'
        }
      }));
    }

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

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

  detectMiningLibrary(script, rules) {
    const knownLibraries = rules.knownMiningLibraries || [
      { name: 'CoinHive', patterns: ['coinhive', 'ch.min.js', 'authedmine'] },
      { name: 'CryptoLoot', patterns: ['cryptoloot', 'cl.min.js'] },
      { name: 'JSEcoin', patterns: ['jsecoin', 'jse.min.js'] },
      { name: 'Minero', patterns: ['minero', 'mr.min.js'] },
      { name: 'Crypto-Loot', patterns: ['crypto-loot'] },
      { name: 'CoinImp', patterns: ['coinimp', 'ci.min.js'] },
      { name: 'Webminer', patterns: ['webminer.js'] }
    ];

    const scriptContent = (script.content || '').toLowerCase();
    const scriptSrc = (script.src || '').toLowerCase();

    for (const lib of knownLibraries) {
      for (const pattern of lib.patterns) {
        if (scriptContent.includes(pattern) || scriptSrc.includes(pattern)) {
          return { name: lib.name };
        }
      }
    }

    return null;
  }

  isSuspiciousWasmModule(wasmModule, rules) {
    // Large WASM modules are suspicious (miners are typically large)
    const sizeThreshold = rules.suspiciousWasmSize || 50000; // 50KB

    if (wasmModule.size > sizeThreshold) {
      return true;
    }

    // Check if loaded from suspicious source
    if (wasmModule.src) {
      const suspiciousDomains = rules.suspiciousMiningDomains || [];
      const moduleSrc = wasmModule.src.toLowerCase();

      if (suspiciousDomains.some(domain => moduleSrc.includes(domain))) {
        return true;
      }
    }

    return false;
  }

  isMiningPoolConnection(connection, rules) {
    const miningPools = rules.miningPoolDomains || [
      { pool: 'Monero', patterns: ['pool.minexmr.com', 'xmr.pool.minergate.com', 'monerohash.com'] },
      { pool: 'Stratum', patterns: ['stratum+tcp', 'stratum+ssl'] },
      { pool: 'Generic', patterns: ['pool.', 'mining.', 'mine.'] }
    ];

    const connectionUrl = (connection.url || '').toLowerCase();

    for (const poolGroup of miningPools) {
      for (const pattern of poolGroup.patterns) {
        if (connectionUrl.includes(pattern)) {
          return { pool: poolGroup.pool };
        }
      }
    }

    return null;
  }

  detectMiningFunctions(scriptContent, rules) {
    const miningFunctionNames = rules.miningFunctionNames || [
      'miner', 'mining', 'hash', 'cryptonight', 'argon2',
      'worker', 'wasm', 'startMining', 'stopMining',
      'getHashesPerSecond', 'getTotalHashes', 'getAcceptedHashes'
    ];

    const found = [];
    const contentLower = scriptContent.toLowerCase();

    for (const funcName of miningFunctionNames) {
      if (contentLower.includes(funcName.toLowerCase())) {
        found.push(funcName);
      }
    }

    return found;
  }
}
