import { SecurityUtils } from "@/security/SecurityConfig.js";

describe("SecurityUtils", () => {
  describe("redactSensitiveData", () => {
    it("should redact password fields", () => {
      const data = {
        username: "testuser",
        password: "secret123",
        apiKey: "abc123",
      };

      const result = SecurityUtils.redactSensitiveData(data);

      expect(result.username).toBe("testuser");
      expect(result.password).toBe("[REDACTED]");
      expect(result.apiKey).toBe("[REDACTED]");
    });

    it("should handle nested objects", () => {
      const data = {
        user: {
          name: "test",
          password: "secret",
        },
        config: {
          token: "xyz789",
        },
      };

      const result = SecurityUtils.redactSensitiveData(data);

      expect(result.user.name).toBe("test");
      expect(result.user.password).toBe("[REDACTED]");
      expect(result.config.token).toBe("[REDACTED]");
    });

    it("should handle arrays", () => {
      const data = [
        { username: "user1", password: "pass1" },
        { username: "user2", secret: "pass2" },
      ];

      const result = SecurityUtils.redactSensitiveData(data);

      expect(result[0].username).toBe("user1");
      expect(result[0].password).toBe("[REDACTED]");
      expect(result[1].username).toBe("user2");
      expect(result[1].secret).toBe("[REDACTED]");
    });
  });

  describe("redactString", () => {
    it("should redact password patterns", () => {
      const text = 'password="secret123" and token="abc456"';
      const result = SecurityUtils.redactString(text);

      expect(result).toContain("[REDACTED]");
      expect(result).not.toContain("secret123");
      expect(result).not.toContain("abc456");
    });

    it("should preserve non-sensitive text", () => {
      const text = "This is a normal message with no secrets";
      const result = SecurityUtils.redactString(text);

      expect(result).toBe(text);
    });
  });

  describe("generateSecureToken", () => {
    it("should generate tokens of specified length", () => {
      const token16 = SecurityUtils.generateSecureToken(16);
      const token32 = SecurityUtils.generateSecureToken(32);

      expect(token16).toHaveLength(16);
      expect(token32).toHaveLength(32);
    });

    it("should generate unique tokens", () => {
      const token1 = SecurityUtils.generateSecureToken(16);
      const token2 = SecurityUtils.generateSecureToken(16);

      expect(token1).not.toBe(token2);
    });

    it("should only contain safe characters", () => {
      const token = SecurityUtils.generateSecureToken(100);
      const safePattern = /^[A-Za-z0-9]+$/;

      expect(safePattern.test(token)).toBe(true);
    });

    it("should use default length when no parameter provided", () => {
      const token = SecurityUtils.generateSecureToken();
      expect(token).toHaveLength(32);
    });
  });

  describe("isFileExtensionAllowed", () => {
    it("should allow safe file extensions", () => {
      expect(SecurityUtils.isFileExtensionAllowed("image.jpg")).toBe(true);
      expect(SecurityUtils.isFileExtensionAllowed("document.pdf")).toBe(true);
      expect(SecurityUtils.isFileExtensionAllowed("data.csv")).toBe(true);
    });

    it("should block dangerous file extensions", () => {
      expect(SecurityUtils.isFileExtensionAllowed("virus.exe")).toBe(false);
      expect(SecurityUtils.isFileExtensionAllowed("script.php")).toBe(false);
      expect(SecurityUtils.isFileExtensionAllowed("malware.bat")).toBe(false);
    });

    it("should be case insensitive", () => {
      expect(SecurityUtils.isFileExtensionAllowed("virus.EXE")).toBe(false);
      expect(SecurityUtils.isFileExtensionAllowed("image.JPG")).toBe(true);
    });
  });

  describe("sanitizeForLog", () => {
    it("should sanitize string data", () => {
      const logData = 'User login with password="secret123"';
      const result = SecurityUtils.sanitizeForLog(logData);

      expect(result).toContain("[REDACTED]");
      expect(result).not.toContain("secret123");
    });

    it("should sanitize object data", () => {
      const logData = {
        action: "login",
        username: "testuser",
        password: "secret123",
      };

      const result = SecurityUtils.sanitizeForLog(logData);

      expect(result.action).toBe("login");
      expect(result.username).toBe("testuser");
      expect(result.password).toBe("[REDACTED]");
    });

    it("should return primitive values unchanged", () => {
      expect(SecurityUtils.sanitizeForLog(123)).toBe(123);
      expect(SecurityUtils.sanitizeForLog(true)).toBe(true);
      expect(SecurityUtils.sanitizeForLog(null)).toBe(null);
    });
  });
});
