import { describe, it, expect, beforeEach, afterEach } from "vitest";
import { join } from "path";
import { mkdir, writeFile, rm } from "fs/promises";
import { tmpdir } from "os";
import { detectBottlenecks, calculateBottleneckScore, } from "../../../scanners/scale/bottleneck-detector.js";
describe("bottleneck-detector", () => {
    let testDir;
    beforeEach(async () => {
        testDir = join(tmpdir(), `bottleneck-test-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
        await mkdir(testDir, { recursive: true });
    });
    afterEach(async () => {
        await rm(testDir, { recursive: true, force: true });
    });
    describe("detectBottlenecks", () => {
        it("detects N+1 query patterns", async () => {
            const srcDir = join(testDir, "src");
            await mkdir(srcDir, { recursive: true });
            const code = `
        const users = await prisma.user.findMany({
          include: {
            posts: true,
            comments: true,
          }
        });
      `;
            await writeFile(join(srcDir, "users.ts"), code);
            const bottlenecks = await detectBottlenecks(testDir);
            const dbBottleneck = bottlenecks.find((b) => b.type === "database");
            expect(dbBottleneck).toBeDefined();
            expect(dbBottleneck?.description).toContain("N+1");
        });
        it("detects blocking operations", async () => {
            const srcDir = join(testDir, "src");
            await mkdir(srcDir, { recursive: true });
            const code = `
        const config = JSON.parse(fs.readFileSync('config.json', 'utf-8'));
        const exists = fs.existsSync(path);
      `;
            await writeFile(join(srcDir, "config.ts"), code);
            const bottlenecks = await detectBottlenecks(testDir);
            const cpuBottleneck = bottlenecks.find((b) => b.type === "cpu");
            expect(cpuBottleneck).toBeDefined();
            expect(cpuBottleneck?.description).toContain("Blocking");
        });
        it("returns empty array for clean code", async () => {
            const srcDir = join(testDir, "src");
            await mkdir(srcDir, { recursive: true });
            const code = `
        export async function getData() {
          const result = await fetch('/api/data');
          return result.json();
        }
      `;
            await writeFile(join(srcDir, "api.ts"), code);
            const bottlenecks = await detectBottlenecks(testDir);
            expect(bottlenecks).toHaveLength(0);
        });
        it("analyzes load test results for high latency", async () => {
            const loadTestResult = {
                profile: "test",
                tool: "k6",
                startTime: new Date().toISOString(),
                endTime: new Date().toISOString(),
                duration: 60000,
                scenarios: [],
                summary: {
                    totalRequests: 1000,
                    failedRequests: 5,
                    errorRate: 0.005,
                    avgThroughput: 100,
                    peakThroughput: 150,
                    latency: {
                        min: 50,
                        max: 2000,
                        mean: 300,
                        median: 250,
                        p90: 450,
                        p95: 800, // High latency
                        p99: 1500,
                    },
                },
                passed: false,
                score: 60,
            };
            const bottlenecks = await detectBottlenecks(testDir, loadTestResult);
            const latencyBottleneck = bottlenecks.find((b) => b.type === "endpoint" && b.description.includes("latency"));
            expect(latencyBottleneck).toBeDefined();
            expect(latencyBottleneck?.severity).toBe("high");
        });
        it("analyzes load test results for high error rate", async () => {
            const loadTestResult = {
                profile: "test",
                tool: "k6",
                startTime: new Date().toISOString(),
                endTime: new Date().toISOString(),
                duration: 60000,
                scenarios: [],
                summary: {
                    totalRequests: 1000,
                    failedRequests: 100, // 10% error rate
                    errorRate: 0.10,
                    avgThroughput: 100,
                    peakThroughput: 150,
                    latency: {
                        min: 50,
                        max: 500,
                        mean: 150,
                        median: 120,
                        p90: 200,
                        p95: 250,
                        p99: 400,
                    },
                },
                passed: false,
                score: 40,
            };
            const bottlenecks = await detectBottlenecks(testDir, loadTestResult);
            const errorBottleneck = bottlenecks.find((b) => b.description.includes("error rate"));
            expect(errorBottleneck).toBeDefined();
            expect(errorBottleneck?.severity).toBe("critical");
        });
    });
    describe("calculateBottleneckScore", () => {
        it("returns 100 for no bottlenecks", () => {
            const score = calculateBottleneckScore([]);
            expect(score).toBe(100);
        });
        it("deducts points for critical bottlenecks", () => {
            const bottlenecks = [
                {
                    type: "endpoint",
                    location: "api",
                    severity: "critical",
                    description: "test",
                    metrics: { current: 0, threshold: 0, unit: "" },
                    recommendation: "",
                },
            ];
            const score = calculateBottleneckScore(bottlenecks);
            expect(score).toBe(75); // -25 for critical
        });
        it("deducts points for multiple bottlenecks", () => {
            const bottlenecks = [
                {
                    type: "endpoint",
                    location: "api",
                    severity: "critical",
                    description: "test",
                    metrics: { current: 0, threshold: 0, unit: "" },
                    recommendation: "",
                },
                {
                    type: "database",
                    location: "queries",
                    severity: "high",
                    description: "test",
                    metrics: { current: 0, threshold: 0, unit: "" },
                    recommendation: "",
                },
                {
                    type: "memory",
                    location: "leak",
                    severity: "medium",
                    description: "test",
                    metrics: { current: 0, threshold: 0, unit: "" },
                    recommendation: "",
                },
            ];
            const score = calculateBottleneckScore(bottlenecks);
            expect(score).toBe(52); // 100 - 25 - 15 - 8
        });
        it("never goes below 0", () => {
            const bottlenecks = Array(10).fill({
                type: "endpoint",
                location: "api",
                severity: "critical",
                description: "test",
                metrics: { current: 0, threshold: 0, unit: "" },
                recommendation: "",
            });
            const score = calculateBottleneckScore(bottlenecks);
            expect(score).toBe(0);
        });
    });
});
//# sourceMappingURL=bottleneck-detector.test.js.map