## Unit Tests for Resolver Cell Manager
##
## This module tests the cell management integration for the dependency resolver.
##
## **Requirements Tested:**
## - 10.3: Maintain separate dependency graphs per cell
## - 10.4: Support cell switching
## - 10.5: Clean up cell-specific packages

import std/[unittest, options, tables, strutils]
import ../src/nip/resolver/cell_manager
import ../src/nip/resolver/nipcell_fallback
import ../src/nip/resolver/dependency_graph
import ../src/nip/resolver/variant_types

# =============================================================================
# Test Helpers
# =============================================================================

proc setupTestManager(): ResolverCellManager =
  ## Create a test cell manager with some pre-populated cells
  result = newResolverCellManager("/tmp/test-resolver-cells")
  
  # Create some test cells
  discard result.graphManager.createCell("dev-cell", "Development environment")
  discard result.graphManager.createCell("prod-cell", "Production environment")
  discard result.graphManager.createCell("test-cell", "Testing environment")

# =============================================================================
# Cell Manager Construction Tests
# =============================================================================

suite "Resolver Cell Manager - Construction":
  test "Create new cell manager":
    let manager = newResolverCellManager("/tmp/test-cells")
    
    check manager != nil
    check manager.graphManager != nil
    check manager.activeResolutions.len == 0
    check manager.cellPackageCache.len == 0

# =============================================================================
# Cell Activation Tests
# =============================================================================

suite "Resolver Cell Manager - Cell Activation":
  test "Activate existing cell":
    let manager = setupTestManager()
    
    let result = manager.activateCell("dev-cell")
    
    check result.success == true
    check result.cellName == "dev-cell"
    check result.error == ""
    check manager.getActiveCellName().isSome
    check manager.getActiveCellName().get() == "dev-cell"
  
  test "Cannot activate non-existent cell":
    let manager = setupTestManager()
    
    let result = manager.activateCell("non-existent")
    
    check result.success == false
    check result.error.contains("not found")
  
  test "Activation tracks previous cell":
    let manager = setupTestManager()
    
    discard manager.activateCell("dev-cell")
    let result = manager.activateCell("prod-cell")
    
    check result.success == true
    check result.previousCell.isSome
    check result.previousCell.get() == "dev-cell"
  
  test "Deactivate cell":
    let manager = setupTestManager()
    
    discard manager.activateCell("dev-cell")
    let success = manager.deactivateCell()
    
    check success == true
    check manager.getActiveCellName().isNone
  
  test "Cannot deactivate when no cell active":
    let manager = setupTestManager()
    
    let success = manager.deactivateCell()
    
    check success == false

# =============================================================================
# Cell Switching Tests
# =============================================================================

suite "Resolver Cell Manager - Cell Switching":
  test "Switch to different cell":
    let manager = setupTestManager()
    
    discard manager.activateCell("dev-cell")
    let result = manager.switchToCell("prod-cell")
    
    check result.success == true
    check result.cellName == "prod-cell"
    check result.previousCell.isSome
    check result.previousCell.get() == "dev-cell"
    check manager.getActiveCellName().get() == "prod-cell"
  
  test "Switch with resolution preservation":
    let manager = setupTestManager()
    
    discard manager.activateCell("dev-cell")
    let result = manager.switchToCell("prod-cell", preserveResolution = true)
    
    check result.success == true
    check result.cellName == "prod-cell"
  
  test "List available cells":
    let manager = setupTestManager()
    
    let cells = manager.listAvailableCells()
    
    check cells.len == 3
    check "dev-cell" in cells
    check "prod-cell" in cells
    check "test-cell" in cells

# =============================================================================
# Cell Removal Tests
# =============================================================================

suite "Resolver Cell Manager - Cell Removal":
  test "Remove cell with package cleanup":
    let manager = setupTestManager()
    
    # Add some packages to the cell
    discard manager.activateCell("dev-cell")
    discard manager.addPackageToActiveCell("nginx")
    discard manager.addPackageToActiveCell("openssl")
    
    let result = manager.removeCell("dev-cell", cleanupPackages = true)
    
    check result.success == true
    check result.cellName == "dev-cell"
    check result.packagesRemoved == 2
    check "dev-cell" notin manager.listAvailableCells()
  
  test "Remove cell without package cleanup":
    let manager = setupTestManager()
    
    discard manager.activateCell("dev-cell")
    discard manager.addPackageToActiveCell("nginx")
    
    let result = manager.removeCell("dev-cell", cleanupPackages = false)
    
    check result.success == true
    check result.packagesRemoved == 1  # Still counts packages
  
  test "Cannot remove non-existent cell":
    let manager = setupTestManager()
    
    let result = manager.removeCell("non-existent")
    
    check result.success == false
    check result.error.contains("not found")
  
  test "Removing active cell deactivates it":
    let manager = setupTestManager()
    
    discard manager.activateCell("dev-cell")
    discard manager.removeCell("dev-cell")
    
    check manager.getActiveCellName().isNone

# =============================================================================
# Package Management Tests
# =============================================================================

suite "Resolver Cell Manager - Package Management":
  test "Add package to active cell":
    let manager = setupTestManager()
    
    discard manager.activateCell("dev-cell")
    let success = manager.addPackageToActiveCell("nginx")
    
    check success == true
    check manager.isPackageInActiveCell("nginx")
  
  test "Cannot add package when no cell active":
    let manager = setupTestManager()
    
    let success = manager.addPackageToActiveCell("nginx")
    
    check success == false
  
  test "Remove package from active cell":
    let manager = setupTestManager()
    
    discard manager.activateCell("dev-cell")
    discard manager.addPackageToActiveCell("nginx")
    
    let success = manager.removePackageFromActiveCell("nginx")
    
    check success == true
    check not manager.isPackageInActiveCell("nginx")
  
  test "Get active cell packages":
    let manager = setupTestManager()
    
    discard manager.activateCell("dev-cell")
    discard manager.addPackageToActiveCell("nginx")
    discard manager.addPackageToActiveCell("openssl")
    discard manager.addPackageToActiveCell("zlib")
    
    let packages = manager.getActiveCellPackages()
    
    check packages.len == 3
    check "nginx" in packages
    check "openssl" in packages
    check "zlib" in packages
  
  test "Packages are isolated between cells":
    let manager = setupTestManager()
    
    # Add packages to dev-cell
    discard manager.activateCell("dev-cell")
    discard manager.addPackageToActiveCell("nginx")
    
    # Add different packages to prod-cell
    discard manager.activateCell("prod-cell")
    discard manager.addPackageToActiveCell("apache")
    
    # Verify isolation
    check manager.isPackageInActiveCell("apache")
    check not manager.isPackageInActiveCell("nginx")
    
    # Switch back to dev-cell
    discard manager.activateCell("dev-cell")
    check manager.isPackageInActiveCell("nginx")
    check not manager.isPackageInActiveCell("apache")

# =============================================================================
# Resolution Integration Tests
# =============================================================================

suite "Resolver Cell Manager - Resolution Integration":
  test "Save and retrieve resolution":
    let manager = setupTestManager()
    
    let graph = newDependencyGraph()
    manager.saveResolution("dev-cell", graph)
    
    let retrieved = manager.getResolution("dev-cell")
    
    check retrieved.isSome
  
  test "Get resolution for non-existent cell":
    let manager = setupTestManager()
    
    let retrieved = manager.getResolution("non-existent")
    
    check retrieved.isNone
  
  test "Resolve in cell context":
    let manager = setupTestManager()
    
    # This would integrate with actual resolver
    # For now, just test the interface
    let graphOpt = manager.resolveInCell("dev-cell", "nginx", VariantDemand())
    
    # Should return the cell's graph (empty for now)
    check graphOpt.isSome

# =============================================================================
# Cell Information Tests
# =============================================================================

suite "Resolver Cell Manager - Cell Information":
  test "Get cell info":
    let manager = setupTestManager()
    
    let info = manager.getCellInfo("dev-cell")
    
    check info.isSome
    check info.get().cellName == "dev-cell"
  
  test "Get cell statistics":
    let manager = setupTestManager()
    
    discard manager.activateCell("dev-cell")
    discard manager.addPackageToActiveCell("nginx")
    discard manager.addPackageToActiveCell("openssl")
    
    let stats = manager.getCellStatistics("dev-cell")
    
    check stats.packageCount == 2
  
  test "Get statistics for non-existent cell":
    let manager = setupTestManager()
    
    let stats = manager.getCellStatistics("non-existent")
    
    check stats.packageCount == 0

# =============================================================================
# Cleanup Operations Tests
# =============================================================================

suite "Resolver Cell Manager - Cleanup Operations":
  test "Cleanup unused packages in cell":
    let manager = setupTestManager()
    
    discard manager.activateCell("dev-cell")
    discard manager.addPackageToActiveCell("nginx")
    discard manager.addPackageToActiveCell("unused-package")
    
    # In a real scenario, unused-package wouldn't be in the graph
    # For now, this tests the interface
    let removed = manager.cleanupUnusedPackages("dev-cell")
    
    check removed >= 0
  
  test "Cleanup all cells":
    let manager = setupTestManager()
    
    # Add packages to multiple cells
    discard manager.activateCell("dev-cell")
    discard manager.addPackageToActiveCell("nginx")
    
    discard manager.activateCell("prod-cell")
    discard manager.addPackageToActiveCell("apache")
    
    let results = manager.cleanupAllCells()
    
    # Results map cell names to number of packages removed
    check results.len >= 0

# =============================================================================
# String Representation Tests
# =============================================================================

suite "Resolver Cell Manager - String Representation":
  test "String representation":
    let manager = setupTestManager()
    
    discard manager.activateCell("dev-cell")
    
    let str = $manager
    
    check str.contains("ResolverCellManager")
    check str.contains("cells: 3")
    check str.contains("active: dev-cell")

# =============================================================================
# Run Tests
# =============================================================================

when isMainModule:
  echo "Running Resolver Cell Manager Tests..."
