## test_gentoo_adapter.nim
## Unit tests for GentooAdapter

import std/[unittest, tables, os, strutils, options]
import ../src/nimpak/build/[types, gentoo_adapter]

suite "GentooAdapter Tests":

  test "GentooAdapter initialization":
    let adapter = newGentooAdapter()

    check adapter != nil
    check adapter.name == "gentoo"
    check adapter.portageDir == "/var/db/repos/gentoo"
    check adapter.pkgDbDir == "/var/db/pkg"
    check adapter.packageCount == 20000

  test "GentooAdapter availability check":
    let adapter = newGentooAdapter()
    let available = adapter.isAvailable()

    # Should match actual system state
    check available == fileExists("/usr/bin/emerge")

  test "Package name validation - valid names":
    let adapter = newGentooAdapter()

    let validNames = @[
      "firefox",
      "app-editors/vim",
      "sys-apps/portage",
      "my-package",
      "package_name",
      "Package123"
    ]

    for name in validNames:
      let request = BuildRequest(
        packageName: name,
        version: "",
        variantFlags: initTable[string, seq[string]](),
        sourceFlags: @[],
        cacheDir: getTempDir(),
        verbose: false
      )

      # Should not raise ValidationError during name validation
      let result = adapter.buildPackage(request)
      # May fail for other reasons, but not validation
      if not result.success and result.errors.len > 0:
        check "Invalid package name" notin result.errors[0]

  test "Package name validation - invalid names":
    let adapter = newGentooAdapter()

    let invalidNames = @[
      "",
      "../etc/passwd",
      "//absolute/path",
      "package;rm -rf /",
      "package`whoami`",
      "package$(whoami)",
      "a" & "b".repeat(300)  # Too long
    ]

    for name in invalidNames:
      let request = BuildRequest(
        packageName: name,
        version: "",
        variantFlags: initTable[string, seq[string]](),
        sourceFlags: @[],
        cacheDir: getTempDir(),
        verbose: false
      )

      let result = adapter.buildPackage(request)
      check result.success == false
      check result.errors.len > 0

  test "package.use generation - no flags":
    let adapter = newGentooAdapter()

    let request = BuildRequest(
      packageName: "test-package",
      version: "",
      variantFlags: initTable[string, seq[string]](),
      sourceFlags: @[],
      cacheDir: getTempDir() / "nip-test-cache",
      verbose: false
    )

    # This will generate the package.use file
    discard adapter.buildPackage(request)

    # Check that package.use file was created
    let useFile = getTempDir() / "nip-test-cache" / "gentoo" / "package.use.test-package"
    if fileExists(useFile):
      let content = readFile(useFile)
      check "# Generated by NIP" in content

  test "package.use generation - with USE flags":
    let adapter = newGentooAdapter()

    let request = BuildRequest(
      packageName: "firefox",
      version: "",
      variantFlags: initTable[string, seq[string]](),
      sourceFlags: @["wayland", "pulseaudio", "-gtk"],
      cacheDir: getTempDir() / "nip-test-cache",
      verbose: false
    )

    discard adapter.buildPackage(request)

    let useFile = getTempDir() / "nip-test-cache" / "gentoo" / "package.use.firefox"
    if fileExists(useFile):
      let content = readFile(useFile)
      check "# Generated by NIP" in content
      check "wayland" in content
      check "pulseaudio" in content
      check "-gtk" in content

  test "USE flag validation - valid flags":
    let adapter = newGentooAdapter()

    let validFlags = @[
      "wayland",
      "pulseaudio",
      "-gtk",
      "+qt5",
      "enable-feature",
      "with_option",
      "flag123"
    ]

    let request = BuildRequest(
      packageName: "test",
      version: "",
      variantFlags: initTable[string, seq[string]](),
      sourceFlags: validFlags,
      cacheDir: getTempDir() / "nip-test-cache",
      verbose: false
    )

    # Should not raise ValidationError
    let result = adapter.buildPackage(request)
    # May fail at build stage, but not at validation
    if not result.success and result.errors.len > 0:
      check "Invalid USE flag" notin result.errors[0]

  test "USE flag validation - invalid flags":
    let adapter = newGentooAdapter()

    # Test with malicious USE flag
    let request = BuildRequest(
      packageName: "test",
      version: "",
      variantFlags: initTable[string, seq[string]](),
      sourceFlags: @["bad;flag"],
      cacheDir: getTempDir() / "nip-test-cache",
      verbose: false
    )

    let result = adapter.buildPackage(request)
    check result.success == false

  test "Build result structure":
    let adapter = newGentooAdapter()

    let request = BuildRequest(
      packageName: "test-package",
      version: "",
      variantFlags: initTable[string, seq[string]](),
      sourceFlags: @[],
      cacheDir: getTempDir() / "nip-test-cache",
      verbose: false
    )

    let result = adapter.buildPackage(request)

    # Check result structure
    check result.source == "gentoo"
    check result.packageName == "test-package"
    # success may be false if package not found, which is expected

  test "Cache directory creation":
    let cacheDir = getTempDir() / "nip-test-cache-gentoo"

    # Remove if exists
    if dirExists(cacheDir):
      removeDir(cacheDir)

    let adapter = newGentooAdapter()
    let request = BuildRequest(
      packageName: "test",
      version: "",
      variantFlags: initTable[string, seq[string]](),
      sourceFlags: @["flag1", "flag2"],  # Add flags to trigger package.use generation
      cacheDir: cacheDir,
      verbose: false
    )

    discard adapter.buildPackage(request)

    # Check that cache directory was created (even if build fails)
    check dirExists(cacheDir / "gentoo") or not fileExists("/usr/bin/emerge")

  test "Variant flags in build result":
    let adapter = newGentooAdapter()

    var variantFlags = initTable[string, seq[string]]()
    variantFlags["graphics"] = @["wayland", "vulkan"]
    variantFlags["audio"] = @["pipewire"]

    let request = BuildRequest(
      packageName: "test",
      version: "",
      variantFlags: variantFlags,
      sourceFlags: @[],
      cacheDir: getTempDir() / "nip-test-cache",
      verbose: false
    )

    let result = adapter.buildPackage(request)

    # Variant flags should be preserved in result
    check result.variantDomains.hasKey("graphics")
    check result.variantDomains.hasKey("audio")

  test "Error handling - package not found":
    let adapter = newGentooAdapter()

    # Use a package name that will definitely not be found
    let request = BuildRequest(
      packageName: "this-package-definitely-does-not-exist-12345",
      version: "",
      variantFlags: initTable[string, seq[string]](),
      sourceFlags: @[],
      cacheDir: getTempDir() / "nip-test-cache",
      verbose: false
    )

    let result = adapter.buildPackage(request)

    # Should fail gracefully
    check result.success == false
    check result.errors.len > 0

  test "Verbose mode":
    let adapter = newGentooAdapter()

    let request = BuildRequest(
      packageName: "test",
      version: "",
      variantFlags: initTable[string, seq[string]](),
      sourceFlags: @[],
      cacheDir: getTempDir() / "nip-test-cache",
      verbose: true
    )

    # Should not crash with verbose mode
    discard adapter.buildPackage(request)

  test "Root privilege warning":
    let adapter = newGentooAdapter()

    let request = BuildRequest(
      packageName: "test",
      version: "",
      variantFlags: initTable[string, seq[string]](),
      sourceFlags: @[],
      cacheDir: getTempDir() / "nip-test-cache",
      verbose: false
    )

    let result = adapter.buildPackage(request)

    # Should include warning about root privileges
    if result.warnings.len > 0:
      var hasRootWarning = false
      for warning in result.warnings:
        if "root" in warning.toLower():
          hasRootWarning = true
          break
      # Warning may or may not be present depending on package found status
      discard hasRootWarning

# Only run search tests if Gentoo is actually available
if fileExists("/usr/bin/emerge"):
  suite "GentooAdapter Search Tests (Gentoo Available)":

    test "Search for package":
      let adapter = newGentooAdapter()

      # Try to search for a common package
      # Note: This test is system-dependent
      let result = adapter.searchPackage("bash")

      # May or may not find it depending on Portage availability
      if result.isSome:
        let info = result.get()
        check info.source == "gentoo"
        check info.available == true

    test "Search for non-existent package":
      let adapter = newGentooAdapter()

      let result = adapter.searchPackage("this-package-does-not-exist-xyz123")

      # Should return none
      check result.isNone

    test "Search with invalid package name":
      let adapter = newGentooAdapter()

      let result = adapter.searchPackage("../etc/passwd")

      # Should return none due to validation
      check result.isNone
