"use strict";
/**
 * Detection Stage — Runs Layer 1 + Layer 2 detectors and handles localhost aggregation.
 *
 * Returns raw findings before noisy aggregation/enrichment (those are called
 * by the orchestrator to keep stage boundaries clean).
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.runLayer2Scan = exports.runLayer1Scan = void 0;
exports.runDetectors = runDetectors;
const secrets_1 = require("./secrets");
const structural_1 = require("./structural");
const urls_1 = require("./config/urls");
const fid = (v) => `${v.filePath}:${v.lineNumber}:${v.category}`;
/**
 * Run all detectors (Layer 1 + Layer 2) and return combined raw findings.
 */
async function runDetectors(input) {
    const { files, middlewareConfig, fileAuthImports, detectorContext, onProgress, cancellationToken, filterPipeline, repoName, quiet, } = input;
    const log = (message) => {
        if (!quiet)
            console.log(message);
    };
    const reportProgress = (status, message, vulnerabilitiesFound = 0) => {
        if (onProgress) {
            onProgress({
                status,
                message,
                filesProcessed: files.length,
                totalFiles: files.length,
                vulnerabilitiesFound,
            });
        }
    };
    const phaseTiming = {};
    // Layer 1: Surface Scan
    const layer1Start = Date.now();
    reportProgress('layer1', 'Running surface scan (patterns, entropy, config)...');
    let layer1Result = await (0, secrets_1.runLayer1Scan)(files, onProgress, cancellationToken);
    // Aggregate repeated localhost findings
    const layer1RawCount = layer1Result.vulnerabilities.length;
    const layer1BeforeAggregation = layer1Result.vulnerabilities;
    layer1Result = {
        ...layer1Result,
        vulnerabilities: (0, urls_1.aggregateLocalhostFindings)(layer1Result.vulnerabilities)
    };
    if (filterPipeline.isEnabled) {
        const afterIds = new Set(layer1Result.vulnerabilities.map(fid));
        for (const v of layer1BeforeAggregation) {
            if (!afterIds.has(fid(v))) {
                filterPipeline.record(fid(v), { stage: 'localhost_aggregation', action: 'aggregated', reason: 'Aggregated repeated localhost finding' });
            }
        }
    }
    phaseTiming.layer1 = Date.now() - layer1Start;
    log(`[Layer1] repo=${repoName} findings_raw=${layer1RawCount} findings_deduped=${layer1Result.vulnerabilities.length} duration=${phaseTiming.layer1}ms`);
    // Layer 2: Structural Scan
    const layer2Start = Date.now();
    reportProgress('layer2', 'Running structural scan (variables, logic gates)...', layer1Result.vulnerabilities.length);
    const layer2Result = await (0, structural_1.runLayer2Scan)(files, { middlewareConfig, fileAuthImports, detectorContext }, onProgress, cancellationToken);
    // Format heuristic breakdown for logging
    const heuristicBreakdown = Object.entries(layer2Result.stats.raw)
        .filter(([, count]) => count > 0)
        .map(([name, count]) => `${name}:${count}`)
        .join(',');
    phaseTiming.layer2 = Date.now() - layer2Start;
    log(`[Layer2] repo=${repoName} findings_raw=${Object.values(layer2Result.stats.raw).reduce((a, b) => a + b, 0)} findings_deduped=${layer2Result.vulnerabilities.length} duration=${phaseTiming.layer2}ms heuristic_breakdown={${heuristicBreakdown}}`);
    // Combine Layer 1 and Layer 2 findings
    const findings = [...layer1Result.vulnerabilities, ...layer2Result.vulnerabilities];
    return { findings, phaseTiming };
}
// Re-export layer results for external consumers
var secrets_2 = require("./secrets");
Object.defineProperty(exports, "runLayer1Scan", { enumerable: true, get: function () { return secrets_2.runLayer1Scan; } });
var structural_2 = require("./structural");
Object.defineProperty(exports, "runLayer2Scan", { enumerable: true, get: function () { return structural_2.runLayer2Scan; } });
//# sourceMappingURL=index.js.map