/**
 * Terraform/IaC Scanner Integration
 *
 * Scans Infrastructure as Code for security misconfigurations
 * using tfsec and checkov.
 *
 * @module scanners/terraform
 */
import { exec } from "child_process";
import { promisify } from "util";
const execAsync = promisify(exec);
export async function checkTfsecAvailable() {
    try {
        const { stdout } = await execAsync("tfsec --version", { timeout: 5000 });
        return {
            scanner: "tfsec",
            available: true,
            version: stdout.trim(),
        };
    }
    catch {
        return {
            scanner: "tfsec",
            available: false,
            error: "tfsec not found. Install from: https://github.com/aquasecurity/tfsec",
        };
    }
}
export async function checkCheckovAvailable() {
    try {
        const { stdout } = await execAsync("checkov --version", { timeout: 5000 });
        return {
            scanner: "checkov",
            available: true,
            version: stdout.trim(),
        };
    }
    catch {
        return {
            scanner: "checkov",
            available: false,
            error: "checkov not found. Install with: pip install checkov",
        };
    }
}
function mapSeverity(severity) {
    switch (severity.toUpperCase()) {
        case "CRITICAL":
            return "critical";
        case "HIGH":
            return "high";
        case "MEDIUM":
            return "medium";
        default:
            return "low";
    }
}
export async function runTfsec(projectPath, options) {
    const startTime = Date.now();
    try {
        const availability = await checkTfsecAvailable();
        if (!availability.available) {
            return {
                scanner: "tfsec",
                findings: [],
                duration: Date.now() - startTime,
                success: false,
                error: availability.error,
            };
        }
        const { stdout } = await execAsync(`tfsec "${projectPath}" --format json --no-color`, {
            timeout: options?.timeout || 120000,
            maxBuffer: 10 * 1024 * 1024,
        }).catch((error) => {
            if (error.stdout) {
                return { stdout: error.stdout, stderr: error.stderr || "" };
            }
            throw error;
        });
        const output = JSON.parse(stdout);
        const findings = (output.results || []).map((result) => ({
            scanner: "tfsec",
            ruleId: `tfsec:${result.rule_id}`,
            file: result.location.filename.replace(projectPath + "/", ""),
            line: result.location.start_line,
            endLine: result.location.end_line,
            message: `${result.rule_description}: ${result.description}`,
            severity: mapSeverity(result.severity),
            confidence: 100,
            metadata: {
                provider: result.rule_provider,
                service: result.rule_service,
                impact: result.impact,
                resolution: result.resolution,
                resource: result.resource,
                links: result.links,
            },
        }));
        return {
            scanner: "tfsec",
            findings,
            duration: Date.now() - startTime,
            success: true,
            version: availability.version,
        };
    }
    catch (error) {
        return {
            scanner: "tfsec",
            findings: [],
            duration: Date.now() - startTime,
            success: false,
            error: error instanceof Error ? error.message : "Unknown error",
        };
    }
}
export async function runCheckov(projectPath, options) {
    const startTime = Date.now();
    try {
        const availability = await checkCheckovAvailable();
        if (!availability.available) {
            return {
                scanner: "checkov",
                findings: [],
                duration: Date.now() - startTime,
                success: false,
                error: availability.error,
            };
        }
        let command = `checkov -d "${projectPath}" -o json --compact`;
        if (options?.framework) {
            command += ` --framework ${options.framework}`;
        }
        const { stdout } = await execAsync(command, {
            timeout: options?.timeout || 180000,
            maxBuffer: 10 * 1024 * 1024,
        }).catch((error) => {
            if (error.stdout) {
                return { stdout: error.stdout, stderr: error.stderr || "" };
            }
            throw error;
        });
        const outputs = JSON.parse(stdout);
        const findings = [];
        for (const output of outputs) {
            for (const result of output.results.failed_checks) {
                findings.push({
                    scanner: "checkov",
                    ruleId: `checkov:${result.check_id}`,
                    file: result.file_path.replace(projectPath + "/", ""),
                    line: result.file_line_range[0],
                    endLine: result.file_line_range[1],
                    message: result.check_name,
                    severity: mapSeverity(result.severity || "MEDIUM"),
                    confidence: 100,
                    metadata: {
                        checkType: output.check_type,
                        resource: result.resource,
                        guideline: result.guideline,
                    },
                });
            }
        }
        return {
            scanner: "checkov",
            findings,
            duration: Date.now() - startTime,
            success: true,
            version: availability.version,
        };
    }
    catch (error) {
        return {
            scanner: "checkov",
            findings: [],
            duration: Date.now() - startTime,
            success: false,
            error: error instanceof Error ? error.message : "Unknown error",
        };
    }
}
export async function runTerraformScanners(projectPath, options) {
    const startTime = Date.now();
    const [tfsecResult, checkovResult] = await Promise.all([
        runTfsec(projectPath, options),
        runCheckov(projectPath, options),
    ]);
    const findings = [...tfsecResult.findings, ...checkovResult.findings];
    const success = tfsecResult.success || checkovResult.success;
    return {
        scanner: "terraform",
        findings,
        duration: Date.now() - startTime,
        success,
        error: !success ? "No IaC scanners available" : undefined,
    };
}
export async function detectTerraform(projectPath) {
    try {
        const { stdout } = await execAsync(`find "${projectPath}" -maxdepth 4 -name "*.tf" -o -name "*.tfvars" -o -name "Pulumi.yaml" -o -name "Pulumi.yml" | head -1`, { timeout: 5000 });
        return stdout.trim().length > 0;
    }
    catch {
        return false;
    }
}
//# sourceMappingURL=terraform.js.map