## Test suite for Nippels Namespace Subsystem Integration (Task 8.2)
##
## Tests the integration of Namespace Subsystem with NippelManager

import std/[unittest, os, times, options, strutils, posix]
import ../src/nimpak/nippels
import ../src/nimpak/namespace_subsystem
import ../src/nimpak/nippel_types
import ../src/nimpak/utils/resultutils

suite "Nippels Namespace Subsystem Integration (Task 8.2)":
  var manager: NippelManager
  let testRoot = getTempDir() / "nippels_namespace_test_" & $epochTime().int
  let isRoot = (getuid() == 0)

  setup:
    # Create test directory
    createDir(testRoot)
    manager = newNippelManager(testRoot)

    # Warn if not running as root
    if not isRoot:
      echo "⚠️  Warning: Not running as root - namespace tests will be limited"

  teardown:
    # Deactivate all active Nippels
    for name in manager.getActiveNippels():
      discard manager.deactivateNippel(name)

    # Clean up test directory
    if dirExists(testRoot):
      removeDir(testRoot)

  test "Create Nippel with None isolation (no namespaces)":
    # Create with custom profile that has None isolation
    let overrides = ProfileOverrides(
      isolationLevel: some(None)
    )

    let result = manager.createNippel("test-none", Homestation, overrides)
    if result.isErr:
      echo "Error creating Nippel: ", result.error
    check result.isOk

    if result.isOk:
      let nippel = result.value
      check nippel.isolationLevel == None
      check nippel.namespaceHandle.isNone

  test "Create Nippel with Standard isolation (mount namespace)":
    let result = manager.createNippel("test-standard", Homestation)
    check result.isOk

    if result.isOk:
      let nippel = result.value
      check nippel.isolationLevel == Standard

      if isRoot:
        # With root, we should have namespaces
        check nippel.namespaceHandle.isSome
        if nippel.namespaceHandle.isSome:
          let nsHandle = nippel.namespaceHandle.get()
          check nsHandle.mountNS == true
          check nsHandle.pidNS == false
          check nsHandle.networkNS == false
      else:
        # Without root, namespace creation falls back to empty handle
        echo "   ℹ️  Skipping namespace checks (not root)"

  test "Create Nippel with Strict isolation (mount + PID + network + IPC)":
    let result = manager.createNippel("test-strict", Server)
    check result.isOk

    if result.isOk:
      let nippel = result.value
      check nippel.isolationLevel == Strict

      if isRoot:
        check nippel.namespaceHandle.isSome
        if nippel.namespaceHandle.isSome:
          let nsHandle = nippel.namespaceHandle.get()
          check nsHandle.mountNS == true
          check nsHandle.pidNS == true
          check nsHandle.networkNS == true
          check nsHandle.ipcNS == true
          check nsHandle.userNS == false
      else:
        echo "   ℹ️  Skipping namespace checks (not root)"

  test "Create Nippel with Quantum isolation (all namespaces)":
    let overrides = ProfileOverrides(
      isolationLevel: some(Quantum)
    )

    let result = manager.createNippel("test-quantum", Server, overrides)
    check result.isOk

    if result.isOk:
      let nippel = result.value
      check nippel.isolationLevel == Quantum

      if isRoot:
        check nippel.namespaceHandle.isSome
        if nippel.namespaceHandle.isSome:
          let nsHandle = nippel.namespaceHandle.get()
          check nsHandle.mountNS == true
          check nsHandle.pidNS == true
          check nsHandle.networkNS == true
          check nsHandle.ipcNS == true
          check nsHandle.userNS == true
          check nsHandle.utsNS == true
      else:
        echo "   ℹ️  Skipping namespace checks (not root)"

  test "Activate Nippel with Standard isolation":
    # Create Nippel
    let createResult = manager.createNippel("test-activate", Homestation)
    check createResult.isOk

    # Activate Nippel
    let activateResult = manager.activateNippel("test-activate")
    check activateResult.isOk

    # Check if active
    check manager.isNippelActive("test-activate")
    check "test-activate" in manager.getActiveNippels()

  test "Activate Nippel with Strict isolation":
    # Create Nippel with Strict isolation
    let createResult = manager.createNippel("test-activate-strict", Server)
    check createResult.isOk

    # Activate Nippel
    let activateResult = manager.activateNippel("test-activate-strict")
    check activateResult.isOk

    # Check if active
    check manager.isNippelActive("test-activate-strict")

  test "Deactivate Nippel":
    # Create and activate Nippel
    let createResult = manager.createNippel("test-deactivate", Homestation)
    check createResult.isOk

    let activateResult = manager.activateNippel("test-deactivate")
    check activateResult.isOk
    check manager.isNippelActive("test-deactivate")

    # Deactivate Nippel
    let deactivateResult = manager.deactivateNippel("test-deactivate")
    check deactivateResult.isOk

    # Check if deactivated
    check not manager.isNippelActive("test-deactivate")
    check "test-deactivate" notin manager.getActiveNippels()

  test "Activate multiple Nippels":
    # Create multiple Nippels
    let result1 = manager.createNippel("test-multi-1", Homestation)
    let result2 = manager.createNippel("test-multi-2", Workstation)
    let result3 = manager.createNippel("test-multi-3", Server)

    check result1.isOk
    check result2.isOk
    check result3.isOk

    # Activate all
    check manager.activateNippel("test-multi-1").isOk
    check manager.activateNippel("test-multi-2").isOk
    check manager.activateNippel("test-multi-3").isOk

    # Check all active
    let activeNippels = manager.getActiveNippels()
    check activeNippels.len == 3
    check "test-multi-1" in activeNippels
    check "test-multi-2" in activeNippels
    check "test-multi-3" in activeNippels

    # Deactivate all
    check manager.deactivateNippel("test-multi-1").isOk
    check manager.deactivateNippel("test-multi-2").isOk
    check manager.deactivateNippel("test-multi-3").isOk

    # Check all deactivated
    check manager.getActiveNippels().len == 0

  test "Error handling: Activate non-existent Nippel":
    let result = manager.activateNippel("non-existent")
    check result.isErr
    check "not found" in result.error.toLowerAscii()

  test "Error handling: Activate already active Nippel":
    # Create and activate
    let createResult = manager.createNippel("test-double-activate", Homestation)
    check createResult.isOk

    let activateResult1 = manager.activateNippel("test-double-activate")
    check activateResult1.isOk

    # Try to activate again
    let activateResult2 = manager.activateNippel("test-double-activate")
    check activateResult2.isErr
    check "already active" in activateResult2.error.toLowerAscii()

  test "Error handling: Deactivate non-active Nippel":
    # Create but don't activate
    let createResult = manager.createNippel("test-not-active", Homestation)
    check createResult.isOk

    # Try to deactivate
    let deactivateResult = manager.deactivateNippel("test-not-active")
    check deactivateResult.isErr
    check "not active" in deactivateResult.error.toLowerAscii()

  test "Namespace configuration matches isolation level":
    # Test Standard isolation
    let nsConfigStandard = getNamespaceHandle(Standard)
    check nsConfigStandard.mountNS == true
    check nsConfigStandard.pidNS == false
    check nsConfigStandard.networkNS == false

    # Test Strict isolation
    let nsConfigStrict = getNamespaceHandle(Strict)
    check nsConfigStrict.mountNS == true
    check nsConfigStrict.pidNS == true
    check nsConfigStrict.networkNS == true
    check nsConfigStrict.ipcNS == true

    # Test Quantum isolation
    let nsConfigQuantum = getNamespaceHandle(Quantum)
    check nsConfigQuantum.mountNS == true
    check nsConfigQuantum.pidNS == true
    check nsConfigQuantum.networkNS == true
    check nsConfigQuantum.ipcNS == true
    check nsConfigQuantum.userNS == true
    check nsConfigQuantum.utsNS == true

  test "Namespace handle is stored in Nippel":
    let result = manager.createNippel("test-ns-handle", Server)
    if result.isErr:
      echo "Error: ", result.error
    check result.isOk

    if result.isOk:
      let nippel = result.value

      if isRoot:
        check nippel.namespaceHandle.isSome
        if nippel.namespaceHandle.isSome:
          let nsHandle = nippel.namespaceHandle.get()
          check nsHandle.nsPath.len > 0
          echo "   Namespace path: ", nsHandle.nsPath
      else:
        echo "   ℹ️  Skipping namespace checks (not root)"

echo "✅ All Task 8.2 tests completed"
