## tests/test_integrity_monitoring.nim
## Tests for integrity monitoring and health checks implementation
##
## This module tests the enhanced integrity monitoring system including:
## - nip verify command with --all support
## - nip doctor --integrity health checks
## - Periodic integrity scanning
## - Real-time filesystem monitoring
## - Integration with runHealthChecks() framework

import std/[unittest, os, times, json, asyncdispatch]
import ../src/nimpak/security/[integrity_monitor, periodic_scanner]
import ../src/nimpak/cli/verify_commands

suite "Integrity Monitoring Tests":

  setup:
    # Create test environment
    if not dirExists("/tmp/test_programs"):
      createDir("/tmp/test_programs")
    if not dirExists("/tmp/test_programs/TestPackage"):
      createDir("/tmp/test_programs/TestPackage")
    if not dirExists("/tmp/test_programs/TestPackage/1.0.0"):
      createDir("/tmp/test_programs/TestPackage/1.0.0")

    # Create a test package file
    writeFile("/tmp/test_programs/TestPackage/1.0.0/TestPackage.npk", "test package content")
    writeFile("/tmp/test_programs/TestPackage/1.0.0/TestPackage.manifest.json", """
{
  "package_hash": "blake2b-test123456789abcdef",
  "version": "1.0.0",
  "files": ["TestPackage.npk"]
}
""")

  teardown:
    # Clean up test environment
    if dirExists("/tmp/test_programs"):
      removeDir("/tmp/test_programs")

  test "Integrity Monitor Initialization":
    let config = getDefaultIntegrityConfig()
    let monitor = newIntegrityMonitor(config)

    check monitor.monitoringEnabled == true
    check monitor.config.enableRealtimeWatcher == true
    check monitor.config.scanInterval == 3600
    check monitor.violationCount == 0

  test "Package Integrity Verification":
    let result = verifyPackageIntegrity("TestPackage", "/tmp/test_programs/TestPackage/1.0.0/TestPackage.npk")

    check result.packageName == "TestPackage"
    check result.checkType == CheckFileIntegrity
    check result.duration >= 0.0
    # Note: This test may fail due to hash mismatch, which is expected for test data

  test "Health Check Registration":
    registerIntegrityHealthChecks()

    # Check that health checks were registered
    check registeredHealthChecks.len > 0

    # Find integrity-related health checks
    var foundIntegrityCheck = false
    for healthCheck in registeredHealthChecks:
      if healthCheck.name == "package-integrity":
        foundIntegrityCheck = true
        break

    check foundIntegrityCheck == true

  test "Verify Command Options Parsing":
    let options1 = parseVerifyCommandOptions(@["--all", "--verbose", "--auto-repair"])
    check options1.target == "--all"
    check options1.verbose == true
    check options1.autoRepair == true
    check options1.checkSignatures == true
    check options1.checkHashes == true

    let options2 = parseVerifyCommandOptions(@["TestPackage", "--no-signatures", "--hashes-only"])
    check options2.target == "TestPackage"
    check options2.checkSignatures == false
    check options2.checkHashes == true

  test "Doctor Integrity Options Parsing":
    let options1 = parseDoctorIntegrityOptions(@["--auto-repair", "--verbose"])
    check options1.autoRepair == true
    check options1.verbose == true
    check options1.showRecommendations == true

    let options2 = parseDoctorIntegrityOptions(@["--no-recommendations"])
    check options2.showRecommendations == false

  test "Periodic Scanner Configuration":
    let schedule = getDefaultScanSchedule()
    check schedule.enabled == true
    check schedule.fullScanInterval == 24
    check schedule.incrementalInterval == 15
    check schedule.fullScanHour == 2

    let config = getDefaultIntegrityConfig()
    let monitor = newIntegrityMonitor(config)
    let scanner = newPeriodicScanner(schedule, monitor)

    check scanner.schedule.enabled == true
    check scanner.isRunning == false
    check scanner.scanHistory.len == 0

  test "Scan ID Generation":
    let scanId1 = generateScanId("full")
    let scanId2 = generateScanId("incremental")

    check scanId1.startsWith("scan_full_")
    check scanId2.startsWith("scan_incremental_")
    check scanId1 != scanId2

  test "Integrity Alert Generation":
    var reporter = newIntegrityReporter(5)

    let violation = IntegrityViolation(
      violationType: "file_modified",
      packageName: "TestPackage",
      filePath: "/tmp/test_programs/TestPackage/1.0.0/TestPackage.npk",
      expectedHash: "blake2b-expected123",
      actualHash: "blake2b-actual456",
      detectedAt: now(),
      severity: SeverityCritical
    )

    let alert = reporter.generateAlert(violation)

    check alert.packageName == "TestPackage"
    check alert.severity == SeverityCritical
    check alert.acknowledged == false
    check reporter.alertHistory.len == 1

  test "Alert Summary Generation":
    var reporter = newIntegrityReporter(3)

    # Generate multiple alerts
    for i in 1..5:
      let violation = IntegrityViolation(
        violationType: "test_violation",
        packageName: fmt"Package{i}",
        filePath: fmt"/tmp/package{i}",
        expectedHash: "hash1",
        actualHash: "hash2",
        detectedAt: now(),
        severity: if i <= 2: SeverityCritical else: SeverityWarning
      )
      discard reporter.generateAlert(violation)

    let summary = reporter.getAlertSummary()

    check summary["total_alerts"].getInt() == 5
    check summary["active_alerts"].getInt() == 5
    check summary["severity_breakdown"]["critical"].getInt() == 2
    check summary["severity_breakdown"]["warning"].getInt() == 3
    check summary["threshold_exceeded"].getBool() == true

  test "Scan Statistics Calculation":
    let schedule = getDefaultScanSchedule()
    let config = getDefaultIntegrityConfig()
    let monitor = newIntegrityMonitor(config)
    var scanner = newPeriodicScanner(schedule, monitor)

    # Add some mock scan results
    let mockResult1 = ScanResult(
      scanId: "test1",
      scanType: "full",
      startTime: now(),
      endTime: now(),
      duration: 10.5,
      packagesScanned: 100,
      issuesFound: 0,
      results: @[],
      success: true
    )

    let mockResult2 = ScanResult(
      scanId: "test2",
      scanType: "incremental",
      startTime: now(),
      endTime: now(),
      duration: 2.3,
      packagesScanned: 5,
      issuesFound: 1,
      results: @[],
      success: false
    )

    scanner.scanHistory.add(mockResult1)
    scanner.scanHistory.add(mockResult2)

    let stats = scanner.getScanStatistics()

    check stats["total_scans"].getInt() == 2
    check stats["successful_scans"].getInt() == 1
    check stats["failed_scans"].getInt() == 1
    check stats["success_rate"].getFloat() == 0.5
    check stats["total_packages_scanned"].getInt() == 105
    check stats["total_issues_found"].getInt() == 1

suite "Async Integrity Monitoring Tests":

  test "Periodic Scanner Scheduling Logic":
    let schedule = ScanSchedule(
      enabled: true,
      fullScanInterval: 24,
      incrementalInterval: 15,
      fullScanHour: 2,
      maxConcurrentScans: 2,
      scanTimeout: 3600
    )

    let config = getDefaultIntegrityConfig()
    let monitor = newIntegrityMonitor(config)
    var scanner = newPeriodicScanner(schedule, monitor)

    # Test when no previous scans
    # Note: This test depends on current time, so we'll just check the logic exists
    let shouldRunFull = scanner.shouldRunFullScan()
    let shouldRunIncremental = scanner.shouldRunIncrementalScan()

    # These are time-dependent, so we just verify they return boolean values
    check shouldRunFull is bool
    check shouldRunIncremental is bool

  test "Health Check Framework Integration":
    # Initialize health checks
    registerIntegrityHealthChecks()

    # Run health checks
    let results = runHealthChecks()

    # Verify that health checks were executed
    # Note: Results may vary based on system state
    check results is seq[IntegrityCheckResult]

echo "Running integrity monitoring tests..."