/**
 * Performance Test: Secret Scanner Throughput
 *
 * Benchmarks the secret scanner's ability to scan content
 * at scale without degrading performance.
 *
 * Covers issue #229 (ORCH-128)
 */
import { describe, it, expect, beforeEach, vi } from "vitest";
import { SecretScannerService } from "../../src/git/secret-scanner.service";
import { ConfigService } from "@nestjs/config";

describe("Performance: Secret Scanner", () => {
  let scanner: SecretScannerService;

  const mockConfigService = {
    get: vi.fn((_key: string, defaultValue?: unknown) => defaultValue),
  };

  beforeEach(() => {
    scanner = new SecretScannerService(mockConfigService as unknown as ConfigService);
  });

  describe("Content scanning throughput", () => {
    it("should scan 1000 lines of clean code in under 50ms", () => {
      const lines = Array.from(
        { length: 1000 },
        (_, i) => `const value${String(i)} = computeResult(${String(i)}, "param-${String(i)}");`
      );
      const content = lines.join("\n");

      const start = performance.now();
      const result = scanner.scanContent(content, "test-file.ts");
      const duration = performance.now() - start;

      expect(duration).toBeLessThan(50);
      expect(result.matches).toHaveLength(0);
    });

    it("should scan 100 files worth of content in under 500ms", () => {
      const fileContent = Array.from(
        { length: 100 },
        (_, i) => `export function handler${String(i)}(): string { return "result-${String(i)}"; }`
      ).join("\n");

      const start = performance.now();

      for (let i = 0; i < 100; i++) {
        scanner.scanContent(fileContent, `file-${String(i)}.ts`);
      }

      const duration = performance.now() - start;
      expect(duration).toBeLessThan(500);
    });

    it("should detect secrets in large content without performance regression", () => {
      // Mix clean code with embedded secrets
      const lines: string[] = [];
      for (let i = 0; i < 500; i++) {
        lines.push(`const config${String(i)} = { host: "localhost", port: ${String(3000 + i)} };`);
      }
      // Insert a secret at line 250
      lines[250] = 'const apiKey = "AKIA1234567890ABCDEF"; // AWS access key';

      const content = lines.join("\n");

      const start = performance.now();
      const result = scanner.scanContent(content, "config.ts");
      const duration = performance.now() - start;

      expect(duration).toBeLessThan(100);
      expect(result.matches.length).toBeGreaterThan(0);
    });

    it("should handle content with many false-positive patterns efficiently", () => {
      // Content with many patterns that look like secrets but are placeholders
      const lines = Array.from(
        { length: 200 },
        (_, i) => `const example_key_${String(i)} = "test-xxxx-example-${String(i)}";`
      );
      const content = lines.join("\n");

      const start = performance.now();
      const result = scanner.scanContent(content, "examples.ts");
      const duration = performance.now() - start;

      expect(duration).toBeLessThan(100);
      // Placeholders should be whitelisted
      expect(result.matches).toHaveLength(0);
    });
  });

  describe("Pattern matching scalability", () => {
    it("should maintain consistent scan time regardless of content position", () => {
      const baseContent = Array.from(
        { length: 1000 },
        (_, i) => `const x${String(i)} = ${String(i)};`
      );

      // Secret at start
      const contentStart = ['const key = "AKIA1234567890ABCDEF";', ...baseContent].join("\n");

      // Secret at end
      const contentEnd = [...baseContent, 'const key = "AKIA1234567890ABCDEF";'].join("\n");

      const startTime1 = performance.now();
      scanner.scanContent(contentStart, "start.ts");
      const duration1 = performance.now() - startTime1;

      const startTime2 = performance.now();
      scanner.scanContent(contentEnd, "end.ts");
      const duration2 = performance.now() - startTime2;

      // Both should complete quickly
      expect(duration1).toBeLessThan(100);
      expect(duration2).toBeLessThan(100);

      // Both should complete within a reasonable ratio (allowing for sub-ms noise)
      const ratio = Math.max(duration1, duration2) / Math.max(0.1, Math.min(duration1, duration2));
      expect(ratio).toBeLessThan(10);
    });
  });
});
