import { describe, it, expect, beforeEach, afterEach } from "vitest";
import { mkdir, rm } from "fs/promises";
import { join } from "path";
import { tmpdir } from "os";
import { loadTrackingData, saveTrackingData, markFalsePositive, markTruePositive, adjustFindingConfidence, generateFPReport, } from "../../scanners/fp-tracker.js";
describe("fp-tracker", () => {
    let testDir;
    beforeEach(async () => {
        testDir = join(tmpdir(), `fp-tracker-test-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
        await mkdir(testDir, { recursive: true });
    });
    afterEach(async () => {
        try {
            await rm(testDir, { recursive: true, force: true });
        }
        catch {
            // Ignore cleanup errors
        }
    });
    describe("loadTrackingData", () => {
        it("returns default data for new project", async () => {
            const data = await loadTrackingData(testDir);
            expect(data.version).toBe("1.0.0");
            expect(data.projectPath).toBe(testDir);
            expect(Object.keys(data.scanners)).toHaveLength(0);
            expect(data.globalStats.totalFindings).toBe(0);
        });
        it("loads existing data", async () => {
            // First save some data
            const initialData = await loadTrackingData(testDir);
            initialData.globalStats.totalFindings = 10;
            await saveTrackingData(testDir, initialData);
            // Then load it
            const loadedData = await loadTrackingData(testDir);
            expect(loadedData.globalStats.totalFindings).toBe(10);
        });
    });
    describe("markFalsePositive", () => {
        it("returns undefined for non-existent scanner", async () => {
            const result = await markFalsePositive(testDir, "semgrep", "some-rule");
            expect(result).toBeUndefined();
        });
        it("updates FP metrics correctly", async () => {
            // First create a scanner and rule entry
            const data = await loadTrackingData(testDir);
            data.scanners["semgrep"] = {
                scanner: "semgrep",
                totalRules: 1,
                totalFindings: 5,
                overallFPRate: 0,
                overallTPRate: 1,
                ruleMetrics: new Map([
                    [
                        "test-rule",
                        {
                            scanner: "semgrep",
                            ruleId: "test-rule",
                            totalReported: 5,
                            confirmedTP: 2,
                            confirmedFP: 0,
                            pendingReview: 3,
                            fpRate: 0,
                            tpRate: 1,
                            adjustmentFactor: 1,
                            lastUpdated: new Date().toISOString(),
                            severityDistribution: {},
                        },
                    ],
                ]),
            };
            await saveTrackingData(testDir, data);
            // Mark as FP
            const result = await markFalsePositive(testDir, "semgrep", "test-rule");
            expect(result).toBeDefined();
            expect(result.confirmedFP).toBe(1);
            expect(result.pendingReview).toBe(2);
            expect(result.fpRate).toBeGreaterThan(0);
        });
    });
    describe("markTruePositive", () => {
        it("updates TP metrics correctly", async () => {
            // First create a scanner and rule entry
            const data = await loadTrackingData(testDir);
            data.scanners["semgrep"] = {
                scanner: "semgrep",
                totalRules: 1,
                totalFindings: 5,
                overallFPRate: 0,
                overallTPRate: 1,
                ruleMetrics: new Map([
                    [
                        "test-rule",
                        {
                            scanner: "semgrep",
                            ruleId: "test-rule",
                            totalReported: 5,
                            confirmedTP: 0,
                            confirmedFP: 2,
                            pendingReview: 3,
                            fpRate: 1,
                            tpRate: 0,
                            adjustmentFactor: 0.1,
                            lastUpdated: new Date().toISOString(),
                            severityDistribution: {},
                        },
                    ],
                ]),
            };
            await saveTrackingData(testDir, data);
            // Mark as TP
            const result = await markTruePositive(testDir, "semgrep", "test-rule");
            expect(result).toBeDefined();
            expect(result.confirmedTP).toBe(1);
            expect(result.pendingReview).toBe(2);
            expect(result.tpRate).toBeGreaterThan(0);
        });
    });
    describe("adjustFindingConfidence", () => {
        it("returns original confidence when no metrics", () => {
            const finding = {
                scanner: "semgrep",
                ruleId: "test",
                file: "test.ts",
                line: 1,
                message: "Test",
                severity: "high",
                confidence: 100,
            };
            const result = adjustFindingConfidence(finding, undefined);
            expect(result).toBe(100);
        });
        it("reduces confidence for high FP rate rules", () => {
            const finding = {
                scanner: "semgrep",
                ruleId: "test",
                file: "test.ts",
                line: 1,
                message: "Test",
                severity: "high",
                confidence: 100,
            };
            const metrics = {
                scanner: "semgrep",
                ruleId: "test",
                totalReported: 10,
                confirmedTP: 2,
                confirmedFP: 8,
                pendingReview: 0,
                fpRate: 0.8,
                tpRate: 0.2,
                adjustmentFactor: 0.28, // 1 - (0.8 * 0.9) = 0.28
                lastUpdated: new Date().toISOString(),
                severityDistribution: {},
            };
            const result = adjustFindingConfidence(finding, metrics);
            expect(result).toBeLessThan(100);
            expect(result).toBe(28);
        });
        it("maintains confidence for low FP rate rules", () => {
            const finding = {
                scanner: "semgrep",
                ruleId: "test",
                file: "test.ts",
                line: 1,
                message: "Test",
                severity: "high",
                confidence: 100,
            };
            const metrics = {
                scanner: "semgrep",
                ruleId: "test",
                totalReported: 10,
                confirmedTP: 9,
                confirmedFP: 1,
                pendingReview: 0,
                fpRate: 0.1,
                tpRate: 0.9,
                adjustmentFactor: 0.91, // 1 - (0.1 * 0.9) = 0.91
                lastUpdated: new Date().toISOString(),
                severityDistribution: {},
            };
            const result = adjustFindingConfidence(finding, metrics);
            expect(result).toBeGreaterThan(90);
        });
        it("clamps confidence to valid range", () => {
            const finding = {
                scanner: "semgrep",
                ruleId: "test",
                file: "test.ts",
                line: 1,
                message: "Test",
                severity: "high",
                confidence: 100,
            };
            const metrics = {
                scanner: "semgrep",
                ruleId: "test",
                totalReported: 10,
                confirmedTP: 0,
                confirmedFP: 10,
                pendingReview: 0,
                fpRate: 1.0,
                tpRate: 0,
                adjustmentFactor: 0.1, // Minimum
                lastUpdated: new Date().toISOString(),
                severityDistribution: {},
            };
            const result = adjustFindingConfidence(finding, metrics);
            expect(result).toBeGreaterThanOrEqual(1);
            expect(result).toBeLessThanOrEqual(100);
        });
    });
    describe("generateFPReport", () => {
        it("generates empty report for new project", async () => {
            const report = await generateFPReport(testDir);
            expect(report.summary.totalScanners).toBe(0);
            expect(report.summary.totalRules).toBe(0);
            expect(report.highFPRules).toHaveLength(0);
        });
        it("includes recommendations for high FP rates", async () => {
            // Create data with high FP rate
            const data = await loadTrackingData(testDir);
            data.scanners["semgrep"] = {
                scanner: "semgrep",
                totalRules: 1,
                totalFindings: 20,
                overallFPRate: 0.8,
                overallTPRate: 0.2,
                ruleMetrics: new Map([
                    [
                        "high-fp-rule",
                        {
                            scanner: "semgrep",
                            ruleId: "high-fp-rule",
                            totalReported: 20,
                            confirmedTP: 4,
                            confirmedFP: 16,
                            pendingReview: 0,
                            fpRate: 0.8,
                            tpRate: 0.2,
                            adjustmentFactor: 0.28,
                            lastUpdated: new Date().toISOString(),
                            severityDistribution: {},
                        },
                    ],
                ]),
            };
            data.globalStats = {
                totalFindings: 20,
                totalTP: 4,
                totalFP: 16,
                totalPending: 0,
                overallAccuracy: 0.2,
            };
            await saveTrackingData(testDir, data);
            const report = await generateFPReport(testDir, { minSampleSize: 5 });
            expect(report.highFPRules.length).toBeGreaterThan(0);
            expect(report.recommendations.length).toBeGreaterThan(0);
        });
    });
});
//# sourceMappingURL=fp-tracker.test.js.map