import { describe, expect, it } from "vitest"
import {
  DEFAULT_SECURITY_IGNORE_DIRS,
  DEFAULT_SECURITY_IGNORE_FILETYPES,
  defaultFileAndFolderSecurityIgnores,
  isSecurityConcern,
} from "./ignore"

describe("isSecurityConcern", () => {
  describe("Security file types", () => {
    it("should detect environment files as security concerns", () => {
      expect(isSecurityConcern(".env")).toBe(true)
      expect(isSecurityConcern(".env.local")).toBe(true)
      expect(isSecurityConcern(".env.production")).toBe(true)
      expect(isSecurityConcern("config/.env")).toBe(true)
      expect(isSecurityConcern("/path/to/.env")).toBe(true)
      expect(isSecurityConcern("file:///path/to/.env")).toBe(true)
    })

    it("should detect configuration files as security concerns", () => {
      expect(isSecurityConcern("config.json")).toBe(true)
      expect(isSecurityConcern("config.yaml")).toBe(true)
      expect(isSecurityConcern("config.yml")).toBe(true)
      expect(isSecurityConcern("settings.json")).toBe(true)
      expect(isSecurityConcern("appsettings.json")).toBe(true)
      expect(isSecurityConcern("appsettings.development.json")).toBe(true)
      expect(isSecurityConcern("appsettings.production.json")).toBe(true)
    })

    it("should detect certificate and key files as security concerns", () => {
      expect(isSecurityConcern("private.key")).toBe(true)
      expect(isSecurityConcern("certificate.pem")).toBe(true)
      expect(isSecurityConcern("server.crt")).toBe(true)
      expect(isSecurityConcern("keystore.jks")).toBe(true)
      expect(isSecurityConcern("ssl/server.key")).toBe(true)
      expect(isSecurityConcern("/etc/ssl/certs/server.pem")).toBe(true)
    })

    it("should detect database files as security concerns", () => {
      expect(isSecurityConcern("database.db")).toBe(true)
      expect(isSecurityConcern("users.sqlite")).toBe(true)
      expect(isSecurityConcern("data.sqlite3")).toBe(true)
      expect(isSecurityConcern("app.mdb")).toBe(true)
      expect(isSecurityConcern("data/users.db")).toBe(true)
    })

    it("should detect credential files as security concerns", () => {
      expect(isSecurityConcern("app.secret")).toBe(true)
      expect(isSecurityConcern("api.secrets")).toBe(true)
      expect(isSecurityConcern("credentials")).toBe(true)
      expect(isSecurityConcern("credentials.json")).toBe(true)
      expect(isSecurityConcern("auth.json")).toBe(true)
      expect(isSecurityConcern("token")).toBe(true)
      expect(isSecurityConcern("api.token")).toBe(true)
      expect(isSecurityConcern("access.token")).toBe(true)
    })

    it("should detect backup files as security concerns", () => {
      expect(isSecurityConcern("database.bak")).toBe(true)
      expect(isSecurityConcern("config.backup")).toBe(true)
      expect(isSecurityConcern("settings.old")).toBe(true)
      expect(isSecurityConcern("app.orig")).toBe(true)
    })

    it("should detect Docker override files as security concerns", () => {
      expect(isSecurityConcern("docker-compose.override.yml")).toBe(true)
      expect(isSecurityConcern("docker-compose.override.yaml")).toBe(true)
    })

    it("should detect SSH and GPG files as security concerns", () => {
      expect(isSecurityConcern("id_rsa")).toBe(true)
      expect(isSecurityConcern("id_dsa")).toBe(true)
      expect(isSecurityConcern("id_ecdsa")).toBe(true)
      expect(isSecurityConcern("id_ed25519")).toBe(true)
      expect(isSecurityConcern("private.ppk")).toBe(true)
      expect(isSecurityConcern("secret.gpg")).toBe(true)
    })
  })

  describe("Security directories", () => {
    it("should detect environment directories as security concerns", () => {
      expect(isSecurityConcern(".env/")).toBe(true)
      expect(isSecurityConcern("env/")).toBe(true)
      expect(isSecurityConcern(".env/config")).toBe(true)
    })

    it("should detect cloud provider directories as security concerns", () => {
      expect(isSecurityConcern(".aws/")).toBe(true)
      expect(isSecurityConcern(".gcp/")).toBe(true)
      expect(isSecurityConcern(".azure/")).toBe(true)
      expect(isSecurityConcern(".kube/")).toBe(true)
      expect(isSecurityConcern(".docker/")).toBe(true)
      expect(isSecurityConcern(".aws/credentials")).toBe(true)
      expect(isSecurityConcern(".kube/config")).toBe(true)
    })

    it("should detect secret directories as security concerns", () => {
      expect(isSecurityConcern("secrets/")).toBe(true)
      expect(isSecurityConcern(".secrets/")).toBe(true)
      expect(isSecurityConcern("private/")).toBe(true)
      expect(isSecurityConcern(".private/")).toBe(true)
      expect(isSecurityConcern("certs/")).toBe(true)
      expect(isSecurityConcern("certificates/")).toBe(true)
      expect(isSecurityConcern("keys/")).toBe(true)
      expect(isSecurityConcern(".ssh/")).toBe(true)
      expect(isSecurityConcern(".gnupg/")).toBe(true)
      expect(isSecurityConcern(".gpg/")).toBe(true)
    })

    it("should detect continue directory as security concern", () => {
      expect(isSecurityConcern(".continue/config.json")).toBe(true)
    })

    it("should detect temporary secret directories as security concerns", () => {
      expect(isSecurityConcern("tmp/secrets/")).toBe(true)
      expect(isSecurityConcern("temp/secrets/")).toBe(true)
      expect(isSecurityConcern(".tmp/")).toBe(true)
      expect(isSecurityConcern("tmp/secrets/api.key")).toBe(true)
    })
  })

  describe("Path variations", () => {
    it("should handle absolute paths", () => {
      expect(isSecurityConcern("/home/user/.env")).toBe(true)
      expect(isSecurityConcern("/var/www/.secrets/")).toBe(true)
      expect(isSecurityConcern("/etc/ssl/private.key")).toBe(true)
    })

    it("should handle URI schemes", () => {
      expect(isSecurityConcern("file:///home/user/.env")).toBe(true)
      expect(isSecurityConcern("file:///var/secrets/api.key")).toBe(true)
    })

    it("should handle nested paths", () => {
      expect(isSecurityConcern("project/config/.env")).toBe(true)
      expect(isSecurityConcern("src/main/resources/application.secret")).toBe(true)
      expect(isSecurityConcern("backend/certs/server.key")).toBe(true)
    })

    // it("should handle Windows-style paths", () => {
    //   expect(isSecurityConcern("C:\\Users\\user\\.env")).toBe(true);
    //   expect(isSecurityConcern("D:\\projects\\app\\secrets\\")).toBe(true);
    // });
  })

  describe("Non-security files", () => {
    it("should not flag regular source code files", () => {
      expect(isSecurityConcern("src/main.js")).toBe(false)
      expect(isSecurityConcern("components/App.tsx")).toBe(false)
      expect(isSecurityConcern("utils/helper.py")).toBe(false)
      expect(isSecurityConcern("models/User.java")).toBe(false)
      expect(isSecurityConcern("styles/main.css")).toBe(false)
    })

    it("should not flag regular configuration files", () => {
      expect(isSecurityConcern("package.json")).toBe(false)
      expect(isSecurityConcern("tsconfig.json")).toBe(false)
      expect(isSecurityConcern("webpack.config.js")).toBe(false)
      expect(isSecurityConcern("babel.config.js")).toBe(false)
      expect(isSecurityConcern("jest.config.js")).toBe(false)
    })

    it("should not flag documentation files", () => {
      expect(isSecurityConcern("README.md")).toBe(false)
      expect(isSecurityConcern("CHANGELOG.md")).toBe(false)
      expect(isSecurityConcern("docs/api.md")).toBe(false)
      expect(isSecurityConcern("LICENSE")).toBe(false)
    })

    it("should not flag regular directories", () => {
      expect(isSecurityConcern("src/")).toBe(false)
      expect(isSecurityConcern("components/")).toBe(false)
      expect(isSecurityConcern("utils/")).toBe(false)
      expect(isSecurityConcern("tests/")).toBe(false)
      expect(isSecurityConcern("docs/")).toBe(false)
    })

    it("should not flag files with similar names but different extensions", () => {
      expect(isSecurityConcern("environment.js")).toBe(false)
      expect(isSecurityConcern("config-template.json")).toBe(false)
      expect(isSecurityConcern("secret-utils.js")).toBe(false)
      expect(isSecurityConcern("token-validator.ts")).toBe(false)
    })
  })

  describe("Edge cases", () => {
    it("should handle empty strings", () => {
      expect(isSecurityConcern("")).toBe(false)
    })

    it("should handle paths with only separators", () => {
      expect(isSecurityConcern("/")).toBe(false)
    })

    it("should handle paths with multiple extensions", () => {
      expect(isSecurityConcern("backup.env.old")).toBe(true) // matches *.old
      expect(isSecurityConcern("config.json.bak")).toBe(true) // matches *.bak
      expect(isSecurityConcern("server.key.backup")).toBe(true) // matches *.backup
    })

    it("should handle files in root vs subdirectories", () => {
      expect(isSecurityConcern(".env")).toBe(true)
      expect(isSecurityConcern("project/.env")).toBe(true)
      expect(isSecurityConcern("deeply/nested/path/.env")).toBe(true)
    })
  })

  describe("Pattern matching consistency", () => {
    it("should match all defined security file patterns", () => {
      // Test a sample from each category to ensure patterns work
      DEFAULT_SECURITY_IGNORE_FILETYPES.forEach((pattern) => {
        // Create a test file name that should match the pattern
        let testFile: string
        if (pattern.startsWith("*.")) {
          testFile = `test${pattern.substring(1)}`
        } else if (pattern.includes("*")) {
          testFile = pattern.replace("*", "test")
        } else {
          testFile = pattern
        }

        expect(isSecurityConcern(testFile)).toBe(true)
      })
    })

    it("should match all defined security directory patterns", () => {
      DEFAULT_SECURITY_IGNORE_DIRS.forEach((pattern) => {
        // Test the directory pattern directly
        expect(isSecurityConcern(pattern)).toBe(true)

        // Test a file inside the directory
        const fileInDir = `${pattern}testfile.txt`
        expect(isSecurityConcern(fileInDir)).toBe(true)
      })
    })
  })

  describe("Integration with ignore library", () => {
    it("should use the same ignore instance as defaultFileAndFolderSecurityIgnores", () => {
      // Test that our function uses the same logic as the exported ignore instance
      const testFiles = [".env", "secrets/api.key", ".aws/credentials", "regular-file.js"]

      testFiles.forEach((file) => {
        const functionResult = isSecurityConcern(file)
        const ignoreResult = defaultFileAndFolderSecurityIgnores.ignores(file)
        expect(functionResult).toBe(ignoreResult)
      })
    })
  })
})
