## NIP Shell REPL Interface
##
## Interactive shell with command parsing, history, and context-aware prompting

import std/[strutils, sequtils, tables, os, terminal, times, options, algorithm, strformat, json]
import ../shell_types, ../types_fixed, core
import commands, enhanced_search, security_integration
# import ../session_manager  # Temporarily disabled

# Type aliases to avoid conflicts
type ShellCommandResult = shell_types.CommandResult

# =============================================================================
# Utility Functions
# =============================================================================

proc editDistance(s1, s2: string): int =
  ## Calculate Levenshtein distance between two strings
  let len1 = s1.len
  let len2 = s2.len

  if len1 == 0: return len2
  if len2 == 0: return len1

  var matrix = newSeq[seq[int]](len1 + 1)
  for i in 0..len1:
    matrix[i] = newSeq[int](len2 + 1)
    matrix[i][0] = i

  for j in 0..len2:
    matrix[0][j] = j

  for i in 1..len1:
    for j in 1..len2:
      let cost = if s1[i-1] == s2[j-1]: 0 else: 1
      matrix[i][j] = min([
        matrix[i-1][j] + 1,      # deletion
        matrix[i][j-1] + 1,      # insertion
        matrix[i-1][j-1] + cost  # substitution
      ])

  return matrix[len1][len2]

# =============================================================================
# Command Completion and Help System
# =============================================================================

type
  CommandVerb* = enum
    # Package management
    Install, Remove, Update, Search, List, Show,
    # Transaction management
    Plan, Commit, Rollback, Status,
    # Session management
    Track, Channel, Policy, Session,
    # Integrity and security
    Verify, Diagnose, Attest, Trust,
    # Utility commands
    Help, Exit, Clear, History,
    # Advanced features
    Query, Macro, Trigger

  CommandCategory* = enum
    PackageManagement, TransactionManagement, SessionManagement,
    SecurityAndIntegrity, UtilityCommands, AdvancedFeatures

  CommandInfo* = object
    verb*: CommandVerb
    category*: CommandCategory
    description*: string
    usage*: string
    examples*: seq[string]
    aliases*: seq[string]

const COMMAND_DATABASE = [
  # Package Management
  CommandInfo(verb: Install, category: PackageManagement,
    description: "Install a package", usage: "install <package> [options]",
    examples: @["install firefox", "install gcc --stream testing"],
    aliases: @["add"]),
  CommandInfo(verb: Remove, category: PackageManagement,
    description: "Remove a package", usage: "remove <package>",
    examples: @["remove firefox", "rm old-package"],
    aliases: @["rm", "uninstall"]),
  CommandInfo(verb: Update, category: PackageManagement,
    description: "Update packages", usage: "update [package]",
    examples: @["update", "update firefox"],
    aliases: @["upgrade"]),
  CommandInfo(verb: Search, category: PackageManagement,
    description: "Search for packages", usage: "search <query>",
    examples: @["search firefox", "find text editor"],
    aliases: @["find"]),
  CommandInfo(verb: List, category: PackageManagement,
    description: "List installed packages", usage: "list [pattern]",
    examples: @["list", "ls lib*", "list --tampered"],
    aliases: @["ls"]),
  CommandInfo(verb: Show, category: PackageManagement,
    description: "Show package information", usage: "show <package>",
    examples: @["show firefox", "info gcc"],
    aliases: @["info"]),

  # Transaction Management
  CommandInfo(verb: Plan, category: TransactionManagement,
    description: "Show current transaction plan", usage: "plan",
    examples: @["plan"], aliases: @[]),
  CommandInfo(verb: Commit, category: TransactionManagement,
    description: "Commit pending transaction", usage: "commit",
    examples: @["commit"], aliases: @[]),
  CommandInfo(verb: Rollback, category: TransactionManagement,
    description: "Rollback last transaction", usage: "rollback [transaction-id]",
    examples: @["rollback", "rollback abc123"], aliases: @[]),
  CommandInfo(verb: Status, category: TransactionManagement,
    description: "Show system status", usage: "status",
    examples: @["status"], aliases: @["st"]),

  # Session Management
  CommandInfo(verb: Track, category: SessionManagement,
    description: "Switch to track", usage: "track [name]",
    examples: @["track", "track testing", "track stable"],
    aliases: @[]),
  CommandInfo(verb: Session, category: SessionManagement,
    description: "Manage sessions", usage: "session <save|load|list|delete> [name]",
    examples: @["session save work", "session load work", "session list"],
    aliases: @[]),

  # Security and Integrity
  CommandInfo(verb: Verify, category: SecurityAndIntegrity,
    description: "Verify package integrity", usage: "verify <package>",
    examples: @["verify firefox", "verify --deep system"],
    aliases: @[]),
  CommandInfo(verb: Diagnose, category: SecurityAndIntegrity,
    description: "Run forensic diagnosis", usage: "diagnose <cid>",
    examples: @["diagnose blake3:abc123", "diagnose firefox"],
    aliases: @[]),
  CommandInfo(verb: Attest, category: SecurityAndIntegrity,
    description: "Create attestation", usage: "attest <package>",
    examples: @["attest firefox"], aliases: @[]),
  CommandInfo(verb: Trust, category: SecurityAndIntegrity,
    description: "Manage trust levels", usage: "trust <key|package>",
    examples: @["trust add-key pubkey.pem"], aliases: @[]),

  # Utility Commands
  CommandInfo(verb: Help, category: UtilityCommands,
    description: "Show help information", usage: "help [command]",
    examples: @["help", "help install", "h search"],
    aliases: @["h"]),
  CommandInfo(verb: History, category: UtilityCommands,
    description: "Show command history", usage: "history",
    examples: @["history"], aliases: @[]),
  CommandInfo(verb: Clear, category: UtilityCommands,
    description: "Clear screen", usage: "clear",
    examples: @["clear"], aliases: @["cls"]),
  CommandInfo(verb: Exit, category: UtilityCommands,
    description: "Exit shell", usage: "exit",
    examples: @["exit"], aliases: @["quit", "q"]),

  # Advanced Features
  CommandInfo(verb: Query, category: AdvancedFeatures,
    description: "Execute SQL query", usage: "query <sql>",
    examples: @["query SELECT * FROM packages"], aliases: @["sql"]),
  CommandInfo(verb: Macro, category: AdvancedFeatures,
    description: "Manage macros", usage: "macro <create|run|list> [name]",
    examples: @["macro list", "macro run deploy"], aliases: @[]),
  CommandInfo(verb: Trigger, category: AdvancedFeatures,
    description: "Manage triggers", usage: "trigger <create|list|delete> [name]",
    examples: @["trigger list"], aliases: @[])
]

proc getAllCommands*(): seq[string] =
  ## Get all available command names including aliases
  var commands: seq[string] = @[]
  for cmd in COMMAND_DATABASE:
    commands.add(($cmd.verb).toLowerAscii())
    for alias in cmd.aliases:
      commands.add(alias)
  return commands.deduplicate().sorted()

proc getCommandInfo*(verb: CommandVerb): CommandInfo =
  ## Get detailed information about a command
  for cmd in COMMAND_DATABASE:
    if cmd.verb == verb:
      return cmd
  # Return default if not found
  return CommandInfo(verb: verb, category: UtilityCommands,
                    description: "Unknown command", usage: $verb)

proc findSimilarCommands*(input: string): seq[string] =
  ## Find commands similar to input (for typo suggestions)
  let allCommands = getAllCommands()
  var suggestions: seq[string] = @[]

  # Exact prefix matches first
  for cmd in allCommands:
    if cmd.startsWith(input.toLowerAscii()):
      suggestions.add(cmd)

  # Then fuzzy matches (edit distance <= 2)
  if suggestions.len < 3:
    for cmd in allCommands:
      if editDistance(input.toLowerAscii(), cmd) <= 2 and cmd notin suggestions:
        suggestions.add(cmd)

  return suggestions[0..min(4, suggestions.len-1)]

proc getCommandsByCategory*(category: CommandCategory): seq[CommandInfo] =
  ## Get all commands in a specific category
  return COMMAND_DATABASE.filterIt(it.category == category)

# =============================================================================
# Command Parsing Types
# =============================================================================

type
  ParsedCommand* = object
    verb*: CommandVerb
    args*: seq[string]
    flags*: Table[string, string]
    raw*: string

  ShellState* = object
    context*: SessionContext
    history*: seq[string]
    running*: bool
    lastCommand*: Option[ParsedCommand]

# =============================================================================
# Command History Management
# =============================================================================

const HISTORY_FILE = ".nip_history"
const MAX_HISTORY = 1000

proc loadHistory(): seq[string] =
  ## Load command history from file
  result = @[]
  let historyPath = getHomeDir() / HISTORY_FILE
  if fileExists(historyPath):
    try:
      for line in lines(historyPath):
        if line.strip().len > 0:
          result.add(line.strip())
      # Keep only last MAX_HISTORY entries
      if result.len > MAX_HISTORY:
        result = result[^MAX_HISTORY..^1]
    except:
      discard  # Ignore errors loading history

proc saveHistory(history: seq[string]) =
  ## Save command history to file
  let historyPath = getHomeDir() / HISTORY_FILE
  try:
    let file = open(historyPath, fmWrite)
    defer: file.close()
    for cmd in history:
      file.writeLine(cmd)
  except:
    discard  # Ignore errors saving history

proc addToHistory(state: var ShellState, command: string) =
  ## Add command to history, avoiding duplicates
  let cmd = command.strip()
  if cmd.len > 0 and (state.history.len == 0 or state.history[^1] != cmd):
    state.history.add(cmd)
    if state.history.len > MAX_HISTORY:
      state.history = state.history[^MAX_HISTORY..^1]

# =============================================================================
# Command Parsing
# =============================================================================

proc parseVerb(word: string): Option[CommandVerb] =
  ## Parse command verb from string
  case word.toLowerAscii():
  of "install", "add": some(Install)
  of "remove", "rm", "uninstall": some(Remove)
  of "update", "upgrade": some(Update)
  of "search", "find": some(Search)
  of "list", "ls": some(List)
  of "show", "info": some(Show)
  of "plan": some(Plan)
  of "commit": some(Commit)
  of "rollback": some(Rollback)
  of "status", "st": some(Status)
  of "track": some(Track)
  of "channel": some(Channel)
  of "policy": some(Policy)
  of "session": some(Session)
  of "verify": some(Verify)
  of "diagnose": some(Diagnose)
  of "attest": some(Attest)
  of "trust": some(Trust)
  of "help", "h": some(Help)
  of "exit", "quit", "q": some(Exit)
  of "clear", "cls": some(Clear)
  of "history": some(History)
  of "query", "sql": some(Query)
  of "macro": some(Macro)
  of "trigger": some(Trigger)
  else: none(CommandVerb)

proc parseCommand(input: string): ParsedCommand =
  ## Parse command line input into structured command
  result = ParsedCommand(
    args: @[],
    flags: initTable[string, string](),
    raw: input
  )

  let parts = input.strip().split()
  if parts.len == 0:
    return

  # Parse verb
  let verbOpt = parseVerb(parts[0])
  if verbOpt.isNone:
    # Unknown command, we'll handle this in execution with suggestions
    result.verb = Help  # Use Help as placeholder
    result.args = @["__unknown__", parts[0]]  # Special marker for unknown commands
    return

  result.verb = verbOpt.get()

  # Parse arguments and flags
  var i = 1
  while i < parts.len:
    let part = parts[i]
    if part.startsWith("--"):
      # Long flag
      let flagParts = part[2..^1].split("=", 1)
      if flagParts.len == 2:
        result.flags[flagParts[0]] = flagParts[1]
      else:
        result.flags[flagParts[0]] = "true"
    elif part.startsWith("-") and part.len > 1:
      # Short flag(s)
      for c in part[1..^1]:
        result.flags[$c] = "true"
    else:
      # Argument
      result.args.add(part)
    inc i

# =============================================================================
# Prompt Generation
# =============================================================================

proc generatePrompt(context: SessionContext): string =
  ## Generate context-aware shell prompt
  var prompt = ""

  # Track indicator
  case context.track:
  of "stable": prompt.add("🟢")
  of "testing": prompt.add("🟡")
  of "dev": prompt.add("🔴")
  else: prompt.add("⚪")

  # Transaction indicator
  if context.transactionId.isSome:
    prompt.add("⚡")

  # Basic prompt
  prompt.add(" nip")

  # Show track if not stable
  if context.track != "stable":
    prompt.add(":" & context.track)

  # Show transaction ID if active
  if context.transactionId.isSome:
    prompt.add("(" & context.transactionId.get()[0..7] & ")")

  prompt.add("> ")
  return prompt

# =============================================================================
# Command Execution Stubs
# =============================================================================

proc executeHelp(args: seq[string]): ShellCommandResult =
  ## Show enhanced help information
  var output = ""

  if args.len > 0:
    # Check if this is an unknown command request
    if args[0] == "__unknown__" and args.len > 1:
      let unknownCmd = args[1]
      let suggestions = findSimilarCommands(unknownCmd)
      output.add("Unknown command: '" & unknownCmd & "'\n")
      if suggestions.len > 0:
        output.add("Did you mean: " & suggestions.join(", ") & "?\n")
      else:
        output.add("Type 'help' to see all available commands.\n")
      return ShellCommandResult(success: false, error: output, duration: 0.001, timestamp: now())

    # Show help for specific command
    let cmdName = args[0].toLowerAscii()
    let verbOpt = parseVerb(cmdName)

    if verbOpt.isSome():
      let info = getCommandInfo(verbOpt.get())
      output.add("Command: " & cmdName & "\n")
      output.add("Description: " & info.description & "\n")
      output.add("Usage: " & info.usage & "\n")

      if info.aliases.len > 0:
        output.add("Aliases: " & info.aliases.join(", ") & "\n")

      if info.examples.len > 0:
        output.add("Examples:\n")
        for example in info.examples:
          output.add("  " & example & "\n")
    else:
      # Command not found, suggest similar ones
      let suggestions = findSimilarCommands(cmdName)
      output.add("Unknown command: " & cmdName & "\n")
      if suggestions.len > 0:
        output.add("Did you mean: " & suggestions.join(", ") & "?\n")
  else:
    # Show categorized help
    output.add("NIP Shell - Interactive Package Management\n\n")

    # Package Management
    output.add("📦 Package Management:\n")
    for cmd in getCommandsByCategory(PackageManagement):
      let aliases = if cmd.aliases.len > 0: " (" & cmd.aliases.join(", ") & ")" else: ""
      output.add("  " & ($cmd.verb).toLowerAscii() & aliases & " - " & cmd.description & "\n")

    # Transaction Management
    output.add("\n⚡ Transaction Management:\n")
    for cmd in getCommandsByCategory(TransactionManagement):
      let aliases = if cmd.aliases.len > 0: " (" & cmd.aliases.join(", ") & ")" else: ""
      output.add("  " & ($cmd.verb).toLowerAscii() & aliases & " - " & cmd.description & "\n")

    # Session Management
    output.add("\n🔧 Session Management:\n")
    for cmd in getCommandsByCategory(SessionManagement):
      let aliases = if cmd.aliases.len > 0: " (" & cmd.aliases.join(", ") & ")" else: ""
      output.add("  " & ($cmd.verb).toLowerAscii() & aliases & " - " & cmd.description & "\n")

    # Security and Integrity
    output.add("\n🔒 Security & Integrity:\n")
    for cmd in getCommandsByCategory(SecurityAndIntegrity):
      let aliases = if cmd.aliases.len > 0: " (" & cmd.aliases.join(", ") & ")" else: ""
      output.add("  " & ($cmd.verb).toLowerAscii() & aliases & " - " & cmd.description & "\n")

    # Utility Commands
    output.add("\n🛠️  Utility Commands:\n")
    for cmd in getCommandsByCategory(UtilityCommands):
      let aliases = if cmd.aliases.len > 0: " (" & cmd.aliases.join(", ") & ")" else: ""
      output.add("  " & ($cmd.verb).toLowerAscii() & aliases & " - " & cmd.description & "\n")

    output.add("\nTip: Use 'help <command>' for detailed information about a specific command\n")
    output.add("     Use TAB for command completion (coming soon)\n")

  ShellCommandResult(
    success: true,
    output: output,
    duration: 0.001,
    timestamp: now()
  )

proc executeExit(): ShellCommandResult =
  ## Exit the shell
  ShellCommandResult(
    success: true,
    output: "Goodbye!",
    duration: 0.001,
    timestamp: now()
  )

proc executeClear(): ShellCommandResult =
  ## Clear the screen
  eraseScreen()
  setCursorPos(0, 0)
  ShellCommandResult(
    success: true,
    output: "",
    duration: 0.001,
    timestamp: now()
  )

proc executeHistory(history: seq[string]): ShellCommandResult =
  ## Show command history
  var output = ""
  for i, cmd in history:
    output.add($(i + 1) & "  " & cmd & "\n")

  ShellCommandResult(
    success: true,
    output: output,
    duration: 0.001,
    timestamp: now()
  )

proc executeSession(state: var ShellState, args: seq[string]): ShellCommandResult =
  ## Execute session management commands (stub)
  ShellCommandResult(
    success: false,
    error: "Session management temporarily disabled",
    duration: 0.001,
    timestamp: now()
  )

proc executeTrack(state: var ShellState, args: seq[string]): ShellCommandResult =
  ## Execute track switching commands
  if args.len == 0:
    return ShellCommandResult(
      success: true,
      output: "Current track: " & state.context.track,
      duration: 0.001,
      timestamp: now()
    )

  let newTrack = args[0].toLowerAscii()
  if newTrack notin ["stable", "testing", "dev", "lts"]:
    return ShellCommandResult(
      success: false,
      error: "Invalid track. Valid tracks: stable, testing, dev, lts",
      duration: 0.001,
      timestamp: now()
    )

  let oldTrack = state.context.track
  state.context.track = newTrack
  state.context.lastUsed = now()

  return ShellCommandResult(
    success: true,
    output: "Switched from " & oldTrack & " to " & newTrack,
    duration: 0.001,
    timestamp: now()
  )

proc executeStatus(state: ShellState): ShellCommandResult =
  ## Show current system status
  var output = "NIP Shell Status:\n"
  output.add("  Track: " & state.context.track & "\n")
  output.add("  Channels: " & state.context.channels.join(", ") & "\n")
  output.add("  Flavor: " & state.context.flavor & "\n")
  output.add("  Toolchain: " & state.context.toolchain & "\n")
  output.add("  Working Dir: " & state.context.workingDir & "\n")

  if state.context.transactionId.isSome:
    output.add("  Active Transaction: " & state.context.transactionId.get() & "\n")
  else:
    output.add("  No active transaction\n")

  output.add("  Session Created: " & state.context.created.format("yyyy-MM-dd HH:mm") & "\n")
  output.add("  Last Used: " & state.context.lastUsed.format("yyyy-MM-dd HH:mm") & "\n")

  if state.context.policy.len > 0:
    output.add("  Policies:\n")
    for key, value in state.context.policy:
      output.add("    " & key & " = " & value & "\n")

  # Add security status summary
  output.add("\n" & displaySecuritySummary())

  return ShellCommandResult(
    success: true,
    output: output,
    duration: 0.001,
    timestamp: now()
  )

# =============================================================================
# Command Result Conversion
# =============================================================================

proc convertResult(coreResult: core.CommandResult): ShellCommandResult =
  ## Convert core.CommandResult to shell CommandResult
  ShellCommandResult(
    success: coreResult.success,
    output: if coreResult.success: coreResult.message else: "",
    error: if not coreResult.success: coreResult.message else: "",
    duration: 0.001,  # We don't track duration in core results
    timestamp: now()
  )

# =============================================================================
# Package Management Commands
# =============================================================================

proc executeInstall(state: var ShellState, args: seq[string], flags: Table[string, string]): ShellCommandResult =
  ## Execute package installation
  if args.len == 0:
    return ShellCommandResult(
      success: false,
      error: "Usage: install <package> [options]",
      duration: 0.001,
      timestamp: now()
    )

  let packageName = args[0]
  let stream = flags.getOrDefault("stream", state.context.track)
  let cell = flags.getOrDefault("cell", "")
  let preview = flags.hasKey("dry-run") or flags.hasKey("n")

  # Use the existing installCommand from commands.nim
  return convertResult(installCommand(packageName, stream, cell, preview))

proc executeRemove(state: var ShellState, args: seq[string]): ShellCommandResult =
  ## Execute package removal
  if args.len == 0:
    return ShellCommandResult(
      success: false,
      error: "Usage: remove <package>",
      duration: 0.001,
      timestamp: now()
    )

  let packageName = args[0]

  # Use the existing removeCommand from commands.nim
  return convertResult(removeCommand(packageName))

proc executeSearch(state: var ShellState, args: seq[string], flags: Table[string, string]): ShellCommandResult =
  ## Execute package search
  if args.len == 0:
    return ShellCommandResult(
      success: false,
      error: "Usage: search <query>",
      duration: 0.001,
      timestamp: now()
    )

  let query = args.join(" ")
  let showVariants = not flags.hasKey("no-variants")
  let showCasPaths = flags.hasKey("cas-paths")

  # Use the search command
  return convertResult(searchCommand(query))

proc executeList(state: var ShellState, args: seq[string], flags: Table[string, string]): ShellCommandResult =
  ## Execute package listing
  let pattern = if args.len > 0: args[0] else: ""
  let showVariants = not flags.hasKey("no-variants")
  let showTampered = flags.hasKey("tampered")

  # Use the list command
  return convertResult(listCommand(true))

proc executeShow(state: var ShellState, args: seq[string]): ShellCommandResult =
  ## Execute package information display
  if args.len == 0:
    return ShellCommandResult(
      success: false,
      error: "Usage: show <package>",
      duration: 0.001,
      timestamp: now()
    )

  let packageName = args[0]

  # Use the existing infoCommand from commands.nim
  return convertResult(infoCommand(packageName))

proc executeUpdate(state: var ShellState, args: seq[string]): ShellCommandResult =
  ## Execute package updates
  if args.len > 0:
    # Update specific package
    let packageName = args[0]
    return ShellCommandResult(
      success: false,
      error: "Specific package updates not implemented yet. Use: update (for all packages)",
      duration: 0.001,
      timestamp: now()
    )
  else:
    # Update all packages
    return convertResult(updateCommand())

# =============================================================================
# Advanced Package Commands
# =============================================================================

proc executeWhere(state: var ShellState, args: seq[string]): ShellCommandResult =
  ## Show CAS paths for a package
  if args.len == 0:
    return ShellCommandResult(
      success: false,
      error: "Usage: where <package>",
      duration: 0.001,
      timestamp: now()
    )

  return convertResult(whereCommand(args[0]))

proc executeVariants(state: var ShellState, args: seq[string]): ShellCommandResult =
  ## Show package variants
  if args.len == 0:
    return ShellCommandResult(
      success: false,
      error: "Usage: variants <package>",
      duration: 0.001,
      timestamp: now()
    )

  return convertResult(variantsCommand(args[0]))

proc executeCid(state: var ShellState, args: seq[string]): ShellCommandResult =
  ## Calculate or show Content Identifier
  if args.len == 0:
    return ShellCommandResult(
      success: false,
      error: "Usage: cid <package> [features...]",
      duration: 0.001,
      timestamp: now()
    )

  return convertResult(cidCommand(args))

proc executeVerify(state: var ShellState, args: seq[string]): ShellCommandResult =
  ## Verify package integrity
  if args.len == 0:
    return ShellCommandResult(
      success: false,
      error: "Usage: verify <package>",
      duration: 0.001,
      timestamp: now()
    )

  let packageName = args[0]
  let verificationResult = executeSecurityVerify(packageName)

  let statusStr = verificationResult{"security_status"}.getStr()
  let detailsStr = verificationResult{"details"}.getStr()
  let verifiedStr = verificationResult{"last_verified"}.getStr()

  return ShellCommandResult(
    success: true,
    output: fmt"🔍 Verification Results for {packageName}:" & "\n" &
            fmt"Status: {formatSecurityStatus(parseEnum[SecurityStatus](statusStr))}" & "\n" &
            fmt"Details: {detailsStr}" & "\n" &
            fmt"Last Verified: {verifiedStr}",
    duration: 0.1,
    timestamp: now()
  )

proc executeDiagnose(state: var ShellState, args: seq[string]): ShellCommandResult =
  ## Run forensic diagnosis
  if args.len == 0:
    return ShellCommandResult(
      success: false,
      error: "Usage: diagnose <package>",
      duration: 0.001,
      timestamp: now()
    )

  let packageName = args[0]
  let diagnosisResult = executeSecurityDiagnose(packageName)
  let diagnosis = diagnosisResult["diagnosis"]

  let statusStr = diagnosis{"security_status"}.getStr()
  let violationsCount = diagnosis{"integrity_violations"}.getInt()
  let detailsStr = diagnosis{"forensic_details"}.getStr()
  let actionStr = diagnosis{"recommended_actions"}[0].getStr()

  return ShellCommandResult(
    success: true,
    output: fmt"🔬 Forensic Diagnosis for {packageName}:" & "\n" &
            fmt"Security Status: {formatSecurityStatus(parseEnum[SecurityStatus](statusStr))}" & "\n" &
            fmt"Integrity Violations: {violationsCount}" & "\n" &
            fmt"Forensic Details: {detailsStr}" & "\n" &
            fmt"Recommended Actions: {actionStr}",
    duration: 0.2,
    timestamp: now()
  )

proc executeCommand(state: var ShellState, cmd: ParsedCommand): ShellCommandResult =
  ## Execute a parsed command
  let startTime = cpuTime()

  var result = case cmd.verb:
  of Help: executeHelp(cmd.args)
  of Exit: executeExit()
  of Clear: executeClear()
  of History: executeHistory(state.history)
  of Session: executeSession(state, cmd.args)
  of Track: executeTrack(state, cmd.args)
  of Status: executeStatus(state)
  # Package Management Commands
  of Install: executeInstall(state, cmd.args, cmd.flags)
  of Remove: executeRemove(state, cmd.args)
  of Search: executeSearch(state, cmd.args, cmd.flags)
  of List: executeList(state, cmd.args, cmd.flags)
  of Show: executeShow(state, cmd.args)
  of Update: executeUpdate(state, cmd.args)
  # Advanced Package Commands
  of Verify: executeVerify(state, cmd.args)
  of Diagnose: executeDiagnose(state, cmd.args)
  # Advanced features (not yet implemented)
  of Plan, Commit, Rollback, Channel, Policy, Attest, Trust, Query, Macro, Trigger:
    ShellCommandResult(
      success: false,
      error: "Command not implemented yet: " & $cmd.verb,
      duration: 0.001,
      timestamp: now()
    )

  result.duration = cpuTime() - startTime
  return result

# =============================================================================
# Main Shell Loop
# =============================================================================

proc initShell*(): ShellState =
  ## Initialize shell state
  ShellState(
    context: newSessionContext(),
    history: loadHistory(),
    running: true
  )

proc runShell*() =
  ## Main shell REPL loop
  var state = initShell()

  echo "NIP Shell v0.1.0 - Interactive Package Management"
  echo "Type 'help' for available commands, 'exit' to quit"
  echo ""

  while state.running:
    # Generate and display prompt
    let prompt = generatePrompt(state.context)
    stdout.write(prompt)
    stdout.flushFile()

    # Read input
    let input = stdin.readLine()

    # Skip empty lines
    if input.strip().len == 0:
      continue

    # Add to history
    state.addToHistory(input)

    # Parse and execute command
    let cmd = parseCommand(input)
    state.lastCommand = some(cmd)

    # Handle exit specially
    if cmd.verb == Exit:
      state.running = false
      continue

    # Execute command
    let result = executeCommand(state, cmd)

    # Display result
    if result.success:
      if result.output.len > 0:
        echo result.output
    else:
      if result.error.len > 0:
        echo "Error: " & result.error

    # Show timing for verbose mode
    if cmd.flags.hasKey("verbose") or cmd.flags.hasKey("v"):
      echo "Command completed in " & $result.duration & "s"

  # Save history and session on exit
  saveHistory(state.history)

  # Save current session as default
  # discard saveAsDefault(state.context)  # Temporarily disabled

  echo "Session saved. Goodbye!"

# =============================================================================
# Public API
# =============================================================================

proc startInteractiveShell*() =
  ## Start the interactive shell
  runShell()