import std/[unittest, os, posix, strutils]
import nip/namespace
import nip/manifest_parser

# Import unshare for testing availability
proc unshare(flags: cint): cint {.importc: "unshare", header: "<sched.h>".}
const CLONE_NEWUSER = 0x10000000

# Note: Testing namespaces usually requires root or unprivileged user namespace support enabled.
# Most CI/Docker environments might block this.
# We will check if we can unshare first.

proc canUnshare(): bool =
  # Try to unshare user namespace
  if unshare(CLONE_NEWUSER) == 0:
    return true
  return false

suite "NIP Namespace Isolation Tests":

  test "Initialize Launcher":
    let manifest = PackageManifest(name: "test-app", version: parseSemanticVersion("1.0.0"), license: "MIT")
    let launcher = newLauncher(manifest, "/tmp/install", "/tmp/cas")
    check launcher != nil
    check launcher.manifest.name == "test-app"

  test "Sandbox Execution (Mock/Check)":
    # This test is tricky without actually running it.
    # We verify the logic compiles and basic object creation works.
    # Actual execution requires a binary to run.
    
    if not canUnshare():
      echo "User namespaces not supported in this environment - SKIPPING"
    else:
      # If we can unshare, we can try a minimal test
      # But 'run' does execv which replaces the process.
      # We need to fork first in the test.
      
      let pid = fork()
      if pid == 0:
        # Child
        try:
          let manifest = PackageManifest(name: "true", version: parseSemanticVersion("1.0.0"), license: "MIT")
          # We point installDir to /bin so it finds 'true' (assuming logic looks in bin/)
          # Wait, the logic looks in installDir/bin/<name>
          # So we need to fake that.
          
          createDir("/tmp/nip_test_ns/bin")
          copyFile("/bin/true", "/tmp/nip_test_ns/bin/true")
          
          let launcher = newLauncher(manifest, "/tmp/nip_test_ns", "/tmp")
          
          # This will replace the process
          launcher.run(@[])
          
          # Should not reach here
          quit(1)
        except Exception as e:
          if "Operation not permitted" in e.msg:
            echo "SKIPPING: Unshare not permitted in child (likely CI restriction)"
            quit(0)
          else:
            echo "Child exception: ", e.msg
            quit(1)
      else:
        # Parent
        var status: cint
        discard waitpid(pid, status, 0)
        check WIFEXITED(status)
        check WEXITSTATUS(status) == 0
