## nimpak/cli/verify_commands.nim
## Enhanced verify command implementations for NimPak CLI
##
## This module implements the enhanced nip verify commands with comprehensive
## integrity monitoring, health checks, and real-time violation detection.

import std/[os, strutils, times, json, sequtils, strformat, algorithm, tables]
import core, ../security/[integrity_monitor, hash_verifier, signature_verifier_working, keyring_manager, event_logger]

type
  VerifyCommandOptions* = object
    target*: string              # Package name or "--all"
    checkSignatures*: bool       # Verify digital signatures
    checkHashes*: bool          # Verify file hashes
    verbose*: bool              # Verbose output
    autoRepair*: bool           # Attempt automatic repair
    showDetails*: bool          # Show detailed verification info
    realTimeWatch*: bool        # Enable real-time monitoring
    periodicScan*: bool         # Enable periodic scanning
    outputFormat*: OutputFormat # Output format

  DoctorIntegrityOptions* = object
    autoRepair*: bool           # Attempt automatic repair
    verbose*: bool              # Verbose output
    showRecommendations*: bool  # Show repair recommendations
    outputFormat*: OutputFormat # Output format

# =============================================================================
# Enhanced nip verify Command Implementation
# =============================================================================

proc parseVerifyCommandOptions*(args: seq[string]): VerifyCommandOptions =
  ## Parse enhanced nip verify command arguments
  var options = VerifyCommandOptions(
    target: "--all",
    checkSignatures: true,
    checkHashes: true,
    verbose: false,
    autoRepair: false,
    showDetails: false,
    realTimeWatch: false,
    periodicScan: false,
    outputFormat: OutputHuman
  )

  var i = 0
  while i < args.len:
    case args[i]:
    of "--all":
      options.target = "--all"
    of "--no-signatures":
      options.checkSignatures = false
    of "--no-hashes":
      options.checkHashes = false
    of "--signatures-only":
      options.checkHashes = false
      options.checkSignatures = true
    of "--hashes-only":
      options.checkSignatures = false
      options.checkHashes = true
    of "--verbose", "-v":
      options.verbose = true
    of "--details":
      options.showDetails = true
    of "--auto-repair":
      options.autoRepair = true
    of "--watch":
      options.realTimeWatch = true
    of "--periodic":
      options.periodicScan = true
    of "--output":
      if i + 1 < args.len:
        case args[i + 1].toLower():
        of "json": options.outputFormat = OutputJson
        of "yaml": options.outputFormat = OutputYaml
        of "kdl": options.outputFormat = OutputKdl
        else: options.outputFormat = OutputHuman
        i += 1
    else:
      # Assume it's a package name
      if options.target == "--all":
        options.target = args[i]
    i += 1

  return options

proc displayVerifyResults*(results: seq[IntegrityCheckResult], options: VerifyCommandOptions) =
  ## Display verification results in human-readable format
  var passed = 0
  var failed = 0
  var totalDuration = 0.0

  echo bold("🔍 Package Verification Results")
  echo "=".repeat(50)

  # Group results by package for cleaner display
  var packageResults = initTable[string, seq[IntegrityCheckResult]]()
  for result in results:
    if result.packageName notin packageResults:
      packageResults[result.packageName] = @[]
    packageResults[result.packageName].add(result)

  # Display results by package
  for packageName in packageResults.keys.toSeq.sorted():
    let packageChecks = packageResults[packageName]
    let packagePassed = packageChecks.allIt(it.success)
    let packageSymbol = if packagePassed: success("✅") else: error("❌")

    echo fmt"{packageSymbol} Package: {bold(packageName)}"

    for result in packageChecks:
      totalDuration += result.duration

      let checkType = case result.checkType:
        of CheckFileIntegrity: "Hash Integrity"
        of CheckSignatureValidity: "Digital Signature"
        of CheckKeyringHealth: "Keyring Health"
        of CheckCRLFreshness: "CRL Freshness"
        of CheckPackageConsistency: "Package Consistency"
        of CheckSystemGeneration: "System Generation"

      let statusSymbol = if result.success: success("  ✓") else: error("  ✗")
      echo fmt"{statusSymbol} {checkType}: {result.message}"

      if result.success:
        inc passed
      else:
        inc failed

      if options.verbose:
        echo fmt"      Duration: {result.duration:.3f}s"
        echo fmt"      Timestamp: {result.checkTime}"

      if options.showDetails and result.details != nil:
        echo "      Details:"
        for key, value in result.details.pairs:
          echo fmt"        {key}: {value}"

    echo ""

  # Summary
  echo bold("📊 Verification Summary")
  echo "=".repeat(30)
  echo fmt"Total checks: {results.len}"
  echo fmt"Passed: {success($passed)}"
  if failed > 0:
    echo fmt"Failed: {error($failed)}"
  else:
    echo fmt"Failed: {$failed}"
  echo fmt"Total time: {totalDuration:.3f}s"
  if results.len > 0:
    echo fmt"Average time per check: {(totalDuration / results.len.float):.3f}s"
  else:
    echo fmt"Average time per check: {0.0}s"

  if failed > 0:
    echo ""
    echo warning("⚠️  Some verification checks failed.")
    if not options.autoRepair:
      echo info("💡 Use --auto-repair to attempt automatic fixes.")
    echo info("💡 Use --verbose for detailed error information.")
    echo info("💡 Use nip doctor --integrity for comprehensive health check.")

proc executeVerifyCommand*(options: VerifyCommandOptions): CommandResult =
  ## Execute the enhanced verify command
  let startTime = cpuTime()

  try:
    if options.verbose:
      showInfo(fmt"🔍 Starting verification: {options.target}")
      if not options.checkHashes:
        showInfo("Hash verification disabled")
      if not options.checkSignatures:
        showInfo("Signature verification disabled")

    # Initialize monitoring system if real-time watch is enabled
    var monitor: IntegrityMonitor
    if options.realTimeWatch or options.periodicScan:
      let config = getDefaultIntegrityConfig()
      monitor = newIntegrityMonitor(config)

    # Execute verification
    var results: seq[IntegrityCheckResult] = @[]

    if options.target == "--all" or options.target == "all":
      results = nipVerifyAllCommand(options.checkSignatures, options.verbose, options.autoRepair)
    else:
      # Verify specific package
      let packagePath = fmt"/Programs/{options.target}/current/{options.target}.npk"
      if fileExists(packagePath):
        results.add(verifyPackageIntegrity(options.target, packagePath))

        if options.checkSignatures:
          let config = getDefaultKeyringConfig()
          var keyringManager = newKeyringManager(config)
          keyringManager.loadAllKeyrings()
          results.add(verifyPackageSignature(options.target, packagePath, keyringManager))
      else:
        results.add(IntegrityCheckResult(
          checkType: CheckFileIntegrity,
          packageName: options.target,
          success: false,
          message: fmt"Package not found: {options.target}",
          details: %*{"package_path": packagePath},
          checkTime: now(),
          duration: 0.0
        ))

    let duration = cpuTime() - startTime

    # Display results
    case options.outputFormat:
    of OutputHuman:
      displayVerifyResults(results, options)

      # Start real-time monitoring if requested
      if options.realTimeWatch:
        showInfo("🔍 Starting real-time filesystem monitoring...")
        # Note: In a real implementation, this would start an async task
        showInfo("Real-time monitoring active. Press Ctrl+C to stop.")

      # Start periodic scanning if requested
      if options.periodicScan:
        showInfo("⏰ Periodic integrity scanning enabled.")
        # Note: In a real implementation, this would start an async task

    else:
      # Structured output
      let outputData = %*{
        "verification_results": results.mapIt(%*{
          "package_name": it.packageName,
          "check_type": $it.checkType,
          "success": it.success,
          "message": it.message,
          "duration": it.duration,
          "timestamp": $it.checkTime,
          "details": it.details
        }),
        "summary": %*{
          "total_checks": results.len,
          "passed_checks": results.countIt(it.success),
          "failed_checks": results.countIt(not it.success),
          "total_duration": duration,
          "target": options.target,
          "options": %*{
            "check_signatures": options.checkSignatures,
            "check_hashes": options.checkHashes,
            "auto_repair": options.autoRepair,
            "real_time_watch": options.realTimeWatch,
            "periodic_scan": options.periodicScan
          }
        }
      }
      outputData(outputData)

    # Determine result
    let failedCount = results.countIt(not it.success)
    if failedCount == 0:
      return successResult(fmt"Verification completed successfully: {results.len} checks passed")
    else:
      return errorResult(fmt"Verification failed: {failedCount} of {results.len} checks failed", 1)

  except Exception as e:
    return errorResult(fmt"Verify command failed: {e.msg}")

# =============================================================================
# Enhanced nip doctor --integrity Command Implementation
# =============================================================================

proc parseDoctorIntegrityOptions*(args: seq[string]): DoctorIntegrityOptions =
  ## Parse nip doctor --integrity command arguments
  var options = DoctorIntegrityOptions(
    autoRepair: false,
    verbose: false,
    showRecommendations: true,
    outputFormat: OutputHuman
  )

  var i = 0
  while i < args.len:
    case args[i]:
    of "--auto-repair":
      options.autoRepair = true
    of "--verbose", "-v":
      options.verbose = true
    of "--no-recommendations":
      options.showRecommendations = false
    of "--output":
      if i + 1 < args.len:
        case args[i + 1].toLower():
        of "json": options.outputFormat = OutputJson
        of "yaml": options.outputFormat = OutputYaml
        of "kdl": options.outputFormat = OutputKdl
        else: options.outputFormat = OutputHuman
        i += 1
    i += 1

  return options

proc displayDoctorIntegrityResults*(result: IntegrityCheckResult, options: DoctorIntegrityOptions) =
  ## Display doctor integrity results in human-readable format
  echo bold("🩺 System Integrity Health Check")
  echo "=".repeat(50)

  let statusSymbol = if result.success: success("✅") else: error("❌")
  let statusText = if result.success: "HEALTHY" else: "ISSUES DETECTED"

  echo fmt"Overall Status: {statusSymbol} {statusText}"
  echo fmt"Check Duration: {result.duration:.3f}s"
  echo fmt"Timestamp: {result.checkTime}"
  echo ""

  echo bold("📋 Health Check Details:")
  echo result.message
  echo ""

  if result.details != nil:
    echo bold("📊 Statistics:")
    let stats = result.details["statistics"]
    let packagesChecked = stats["packages_checked"].getInt()
    let integrityPassed = stats["integrity_passed"].getInt()
    let integrityFailed = stats["integrity_failed"].getInt()
    echo fmt"Packages checked: {packagesChecked}"
    echo fmt"Integrity passed: {integrityPassed}"
    echo fmt"Integrity failed: {integrityFailed}"
    let signaturesVerified = stats["signatures_verified"].getInt()
    let signaturesFailed = stats["signatures_failed"].getInt()
    let revokedKeysFound = stats["revoked_keys_found"].getInt()
    echo fmt"Signatures verified: {signaturesVerified}"
    echo fmt"Signatures failed: {signaturesFailed}"
    echo fmt"Revoked keys found: {revokedKeysFound}"
    echo ""

    if result.details.hasKey("issues") and result.details["issues"].len > 0:
      echo bold("⚠️  Issues Found:")
      for issue in result.details["issues"]:
        echo fmt"  • {issue.getStr()}"
      echo ""

  if options.showRecommendations and not result.success:
    echo bold("💡 Recommendations:")
    echo "  1. Run 'nip verify --all --verbose' for detailed package verification"
    echo "  2. Check system logs with 'nip audit log --follow'"
    echo "  3. Update keyrings with 'nip key update' if signature issues found"
    if options.autoRepair:
      echo "  4. Auto-repair was attempted - check results above"
    else:
      echo "  4. Use --auto-repair to attempt automatic fixes"
    echo ""

proc executeDoctorIntegrityCommand*(options: DoctorIntegrityOptions): CommandResult =
  ## Execute the enhanced doctor integrity command
  try:
    if options.verbose:
      showInfo("🩺 Starting comprehensive integrity health check...")

    # Execute integrity health check
    let result = nipDoctorIntegrityCommand(options.autoRepair, options.verbose)

    # Display results
    case options.outputFormat:
    of OutputHuman:
      displayDoctorIntegrityResults(result, options)

    else:
      # Structured output
      let outputData = %*{
        "health_check_result": %*{
          "check_type": $result.checkType,
          "package_name": result.packageName,
          "success": result.success,
          "message": result.message,
          "duration": result.duration,
          "timestamp": $result.checkTime,
          "details": result.details
        },
        "options": %*{
          "auto_repair": options.autoRepair,
          "verbose": options.verbose,
          "show_recommendations": options.showRecommendations
        }
      }
      outputData(outputData)

    # Return appropriate result
    if result.success:
      return successResult("System integrity health check passed - no issues found")
    else:
      return errorResult("System integrity health check found issues", 1)

  except Exception as e:
    return errorResult(fmt"Doctor integrity command failed: {e.msg}")

# =============================================================================
# Integration with runHealthChecks() Framework
# =============================================================================

proc initializeIntegrityHealthChecks*() =
  ## Initialize and register integrity health checks with the framework
  registerIntegrityHealthChecks()

  showInfo("🔧 Integrity health checks registered with framework")

proc runScheduledIntegrityChecks*(): seq[IntegrityCheckResult] =
  ## Run scheduled integrity checks via the health check framework
  return runHealthChecks()

# =============================================================================
# Export main functions
# =============================================================================

export VerifyCommandOptions, DoctorIntegrityOptions
export parseVerifyCommandOptions, parseDoctorIntegrityOptions
export executeVerifyCommand, executeDoctorIntegrityCommand
export initializeIntegrityHealthChecks, runScheduledIntegrityChecks