## update_commands.nim
## CLI commands for automatic updates

import std/[strutils, times]
import ../update/[update_checker, update_manager]

proc updateCheckCommand*(force: bool = false): int =
  ## Check for available updates
  let checker = newUpdateChecker()

  if not force and not checker.shouldCheck():
    echo "ℹ️  Update check not needed yet"
    echo "   Last check: ", checker.config.lastCheck.format("yyyy-MM-dd HH:mm:ss")
    echo "   Frequency: ", $checker.config.frequency
    echo ""
    echo "Use --force to check anyway"
    return 0

  echo "🔍 Checking for updates..."
  echo ""

  let updates = checker.checkAllUpdates()

  if updates.len == 0:
    echo "✅ All components are up to date"
    return 0

  showUpdateNotifications(updates)
  return 0

proc updateRecipesCommand*(verbose: bool = false): int =
  ## Update recipe repository
  let manager = newUpdateManager(verbose)

  let result = manager.updateRecipes()

  if result.success:
    return 0
  else:
    echo ""
    echo "Errors:"
    for error in result.errors:
      echo "  • ", error
    return 1

proc updateToolCommand*(toolName: string, verbose: bool = false): int =
  ## Update a specific tool
  let manager = newUpdateManager(verbose)

  let result = manager.updateTool(toolName)

  if result.success:
    return 0
  else:
    echo ""
    echo "Errors:"
    for error in result.errors:
      echo "  • ", error
    return 1

proc updateSelfCommand*(verbose: bool = false): int =
  ## Update NIP itself
  let checker = newUpdateChecker()
  let updateInfo = checker.checkNipUpdates()

  if updateInfo.isNone:
    echo "✅ NIP is already up to date"
    return 0

  let info = updateInfo.get()

  echo "📦 NIP Update Available"
  echo ""
  echo "Current Version: ", info.currentVersion
  echo "Latest Version:  ", info.latestVersion
  echo ""

  if info.changelog.len > 0:
    echo "Changelog:"
    echo info.changelog
    echo ""

  stdout.write("Update now? (y/N): ")
  stdout.flushFile()

  let response = stdin.readLine().strip().toLower()

  if response != "y" and response != "yes":
    echo "Update cancelled"
    return 0

  let manager = newUpdateManager(verbose)
  let result = manager.updateNip(info.downloadUrl)

  if result.success:
    return 0
  else:
    echo ""
    echo "Errors:"
    for error in result.errors:
      echo "  • ", error
    return 1

proc updateAllCommand*(verbose: bool = false): int =
  ## Update all components
  let manager = newUpdateManager(verbose)

  let results = manager.updateAll()

  var allSuccess = true
  for result in results:
    if not result.success:
      allSuccess = false

  if allSuccess:
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo "✅ All updates completed successfully"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    return 0
  else:
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo "⚠️  Some updates failed"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    return 1

proc updateConfigCommand*(
  enable: bool = false,
  disable: bool = false,
  channel: string = "",
  frequency: string = "",
  notifyRecipes: string = "",
  notifyTools: string = "",
  notifyNip: string = ""
): int =
  ## Configure automatic updates
  var config = loadConfig()

  if enable:
    config.enabled = true
    echo "✅ Automatic updates enabled"

  if disable:
    config.enabled = false
    echo "✅ Automatic updates disabled"

  if channel.len > 0:
    case channel.toLower()
    of "stable":
      config.channel = Stable
      echo "✅ Update channel set to: stable"
    of "beta":
      config.channel = Beta
      echo "✅ Update channel set to: beta"
    of "nightly":
      config.channel = Nightly
      echo "✅ Update channel set to: nightly"
    else:
      echo "❌ Invalid channel: ", channel
      echo "   Valid channels: stable, beta, nightly"
      return 1

  if frequency.len > 0:
    case frequency.toLower()
    of "never":
      config.frequency = Never
      echo "✅ Update frequency set to: never"
    of "daily":
      config.frequency = Daily
      echo "✅ Update frequency set to: daily"
    of "weekly":
      config.frequency = Weekly
      echo "✅ Update frequency set to: weekly"
    of "monthly":
      config.frequency = Monthly
      echo "✅ Update frequency set to: monthly"
    else:
      echo "❌ Invalid frequency: ", frequency
      echo "   Valid frequencies: never, daily, weekly, monthly"
      return 1

  if notifyRecipes.len > 0:
    config.notifyRecipes = notifyRecipes.toLower() in ["true", "yes", "1"]
    echo "✅ Recipe notifications: ", config.notifyRecipes

  if notifyTools.len > 0:
    config.notifyTools = notifyTools.toLower() in ["true", "yes", "1"]
    echo "✅ Tool notifications: ", config.notifyTools

  if notifyNip.len > 0:
    config.notifyNip = notifyNip.toLower() in ["true", "yes", "1"]
    echo "✅ NIP notifications: ", config.notifyNip

  saveConfig(config)
  return 0

proc updateStatusCommand*(): int =
  ## Show update configuration and status
  let config = loadConfig()

  echo "Update Configuration"
  echo "===================="
  echo ""
  echo "Enabled: ", if config.enabled: "Yes" else: "No"
  echo "Channel: ", $config.channel
  echo "Frequency: ", $config.frequency
  echo "Last Check: ", config.lastCheck.format("yyyy-MM-dd HH:mm:ss")
  echo ""
  echo "Notifications:"
  echo "  Recipes: ", if config.notifyRecipes: "Yes" else: "No"
  echo "  Tools: ", if config.notifyTools: "Yes" else: "No"
  echo "  NIP: ", if config.notifyNip: "Yes" else: "No"
  echo ""

  # Check if updates are available
  let checker = newUpdateChecker(config)
  if checker.shouldCheck():
    echo "🔍 Checking for updates..."
    let updates = checker.checkAllUpdates()

    if updates.len > 0:
      echo ""
      showUpdateNotifications(updates, quiet = false)
    else:
      echo "✅ All components are up to date"

  return 0

proc rollbackCommand*(component: string, verbose: bool = false): int =
  ## Rollback a component to previous version
  let manager = newUpdateManager(verbose)

  echo "🔄 Rolling back: ", component
  echo ""

  let success = manager.rollback(component)

  if success:
    echo "✅ Rollback successful"
    return 0
  else:
    echo "❌ Rollback failed"
    return 1

proc listBackupsCommand*(): int =
  ## List available backups
  let manager = newUpdateManager()
  let backups = manager.listBackups()

  if backups.len == 0:
    echo "No backups found"
    return 0

  echo "Available Backups:"
  echo "=================="
  echo ""

  for backup in backups:
    echo "  ", backup.name
    echo "    Date: ", backup.date.format("yyyy-MM-dd HH:mm:ss")
    echo "    Path: ", backup.path
    echo ""

  echo "Total: ", backups.len, " backups"
  return 0

proc cleanBackupsCommand*(keepDays: int = 30, verbose: bool = false): int =
  ## Clean old backups
  let manager = newUpdateManager(verbose)

  echo "🗑️  Cleaning backups older than ", keepDays, " days..."

  let removed = manager.cleanOldBackups(keepDays)

  if removed > 0:
    echo "✅ Removed ", removed, " old backups"
  else:
    echo "✅ No old backups to remove"

  return 0

proc updateHelpCommand*(): int =
  ## Show update command help
  echo """
NIP Update Commands
===================

Automatic updates keep NIP, recipes, and tools up to date.

Commands:
  nip update check              Check for available updates
    --force                     Force check even if not due

  nip update recipes            Update recipe repository
  nip update tool <name>        Update specific tool
  nip update self               Update NIP itself
  nip update all                Update all components

  nip update config             Configure automatic updates
    --enable                    Enable automatic updates
    --disable                   Disable automatic updates
    --channel <stable|beta|nightly>  Set update channel
    --frequency <never|daily|weekly|monthly>  Set check frequency
    --notify-recipes <yes|no>   Enable/disable recipe notifications
    --notify-tools <yes|no>     Enable/disable tool notifications
    --notify-nip <yes|no>       Enable/disable NIP notifications

  nip update status             Show update configuration
  nip update rollback <component>  Rollback to previous version
  nip update backups            List available backups
  nip update clean-backups      Clean old backups
    --keep-days <days>          Keep backups newer than N days (default: 30)

Examples:
  # Check for updates
  nip update check

  # Update recipes
  nip update recipes

  # Update all components
  nip update all

  # Configure automatic updates
  nip update config --enable --frequency weekly

  # Rollback recipes to previous version
  nip update rollback recipes

  # Clean old backups
  nip update clean-backups --keep-days 7

Configuration:
  Config file: ~/.config/nip/update-config.json
  Backups: ~/.cache/nip/backups/

Update Channels:
  stable  - Stable releases (recommended)
  beta    - Beta releases (early access)
  nightly - Nightly builds (bleeding edge)

Update Frequency:
  never   - Manual updates only
  daily   - Check daily
  weekly  - Check weekly (recommended)
  monthly - Check monthly

For more information:
  https://git.maiwald.work/Nexus/NexusToolKit/wiki/Automatic-Updates
"""
  return 0
