package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"math/rand"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"time"

	"github.com/Fimeg/RedFlag/aggregator-agent/internal/acknowledgment"
	"github.com/Fimeg/RedFlag/aggregator-agent/internal/cache"
	"github.com/Fimeg/RedFlag/aggregator-agent/internal/circuitbreaker"
	"github.com/Fimeg/RedFlag/aggregator-agent/internal/client"
	"github.com/Fimeg/RedFlag/aggregator-agent/internal/config"
	"github.com/Fimeg/RedFlag/aggregator-agent/internal/constants"
	"github.com/Fimeg/RedFlag/aggregator-agent/internal/crypto"
	"github.com/Fimeg/RedFlag/aggregator-agent/internal/display"
	"github.com/Fimeg/RedFlag/aggregator-agent/internal/guardian"
	"github.com/Fimeg/RedFlag/aggregator-agent/internal/handlers"
	"github.com/Fimeg/RedFlag/aggregator-agent/internal/installer"
	"github.com/Fimeg/RedFlag/aggregator-agent/internal/logging"
	"github.com/Fimeg/RedFlag/aggregator-agent/internal/migration"
	"github.com/Fimeg/RedFlag/aggregator-agent/internal/orchestrator"
	"github.com/Fimeg/RedFlag/aggregator-agent/internal/scanner"
	"github.com/Fimeg/RedFlag/aggregator-agent/internal/service"
	"github.com/Fimeg/RedFlag/aggregator-agent/internal/system"
	"github.com/Fimeg/RedFlag/aggregator-agent/internal/validator"
	"github.com/Fimeg/RedFlag/aggregator-agent/internal/version"
	"github.com/google/uuid"
)

var (
	lastConfigVersion int64 = 0 // Track last applied config version
)

// reportLogWithAck reports a command log to the server and tracks it for acknowledgment
func reportLogWithAck(apiClient *client.Client, cfg *config.Config, ackTracker *acknowledgment.Tracker, logReport client.LogReport) error {
	// Track this command result as pending acknowledgment
	ackTracker.Add(logReport.CommandID)

	// Save acknowledgment state immediately
	if err := ackTracker.Save(); err != nil {
		log.Printf("Warning: Failed to save acknowledgment for command %s: %v", logReport.CommandID, err)
	}

	// Report the log to the server (FIX: was calling itself recursively!)
	if err := apiClient.ReportLog(cfg.AgentID, logReport); err != nil {
		// If reporting failed, increment retry count but don't remove from pending
		ackTracker.IncrementRetry(logReport.CommandID)
		return err
	}

	return nil
}

// calculateBackoff returns an exponential backoff delay with full jitter (F-B2-7 fix).
// Pattern: delay = rand(0, min(cap, base * 2^attempt))
// TODO: make base and cap configurable via agent config
func calculateBackoff(attempt int) time.Duration {
	base := 10 * time.Second
	cap := 5 * time.Minute

	// Calculate ceiling: base * 2^attempt, capped at max
	ceiling := base * time.Duration(1<<uint(attempt))
	if ceiling > cap || ceiling <= 0 { // overflow protection
		ceiling = cap
	}

	// Full jitter: random duration between 0 and ceiling
	delay := time.Duration(rand.Int63n(int64(ceiling)))
	if delay < base {
		delay = base // minimum delay of base
	}
	return delay
}

// getCurrentPollingInterval returns the appropriate polling interval based on rapid mode
func getCurrentPollingInterval(cfg *config.Config) int {
	// Check if rapid polling mode is active and not expired
	if cfg.RapidPollingEnabled && time.Now().Before(cfg.RapidPollingUntil) {
		return 5 // Rapid polling: 5 seconds
	}

	// Check if rapid polling has expired and clean up
	if cfg.RapidPollingEnabled && time.Now().After(cfg.RapidPollingUntil) {
		cfg.RapidPollingEnabled = false
		cfg.RapidPollingUntil = time.Time{}
		// Save the updated config to clean up expired rapid mode
		if err := cfg.Save(constants.GetAgentConfigPath()); err != nil {
			log.Printf("Warning: Failed to cleanup expired rapid polling mode: %v", err)
		}
	}

	return cfg.CheckInInterval // Normal polling: 5 minutes (300 seconds) by default
}

// getDefaultServerURL returns the default server URL with environment variable support
func getDefaultServerURL() string {
	// Check environment variable first
	if envURL := os.Getenv("REDFLAG_SERVER_URL"); envURL != "" {
		return envURL
	}

	// Platform-specific defaults
	if runtime.GOOS == "windows" {
		// For Windows, use a placeholder that prompts users to configure
		return "http://REPLACE_WITH_SERVER_IP:8080"
	}
	return "http://localhost:8080"
}

func main() {
	// Define CLI flags
	registerCmd := flag.Bool("register", false, "Register agent with server")
	scanCmd := flag.Bool("scan", false, "Scan for updates and display locally")
	statusCmd := flag.Bool("status", false, "Show agent status")
	listUpdatesCmd := flag.Bool("list-updates", false, "List detailed update information")
	versionCmd := flag.Bool("version", false, "Show version information")
	serverURL := flag.String("server", "", "Server URL")
	registrationToken := flag.String("token", "", "Registration token for secure enrollment")
	proxyHTTP := flag.String("proxy-http", "", "HTTP proxy URL")
	proxyHTTPS := flag.String("proxy-https", "", "HTTPS proxy URL")
	proxyNoProxy := flag.String("proxy-no", "", "Comma-separated hosts to bypass proxy")
	logLevel := flag.String("log-level", "", "Log level (debug, info, warn, error)")
	configFile := flag.String("config", "", "Configuration file path")
	tagsFlag := flag.String("tags", "", "Comma-separated tags for agent")
	organization := flag.String("organization", "", "Organization/group name")
	displayName := flag.String("name", "", "Display name for agent")
	insecureTLS := flag.Bool("insecure-tls", false, "Skip TLS certificate verification")
	exportFormat := flag.String("export", "", "Export format: json, csv")

	// Windows service management commands
	installServiceCmd := flag.Bool("install-service", false, "Install as Windows service")
	removeServiceCmd := flag.Bool("remove-service", false, "Remove Windows service")
	startServiceCmd := flag.Bool("start-service", false, "Start Windows service")
	stopServiceCmd := flag.Bool("stop-service", false, "Stop Windows service")
	serviceStatusCmd := flag.Bool("service-status", false, "Show Windows service status")
	flag.Parse()

	// Handle version command
	if *versionCmd {
		fmt.Printf("RedFlag Agent v%s\n", version.Version)
		fmt.Printf("Self-hosted update management platform\n")
		os.Exit(0)
	}

	// Handle Windows service management commands (only on Windows)
	if runtime.GOOS == "windows" {
		if *installServiceCmd {
			if err := service.InstallService(); err != nil {
				log.Fatalf("Failed to install service: %v", err)
			}
			fmt.Println("RedFlag service installed successfully")
			os.Exit(0)
		}

		if *removeServiceCmd {
			if err := service.RemoveService(); err != nil {
				log.Fatalf("Failed to remove service: %v", err)
			}
			fmt.Println("RedFlag service removed successfully")
			os.Exit(0)
		}

		if *startServiceCmd {
			if err := service.StartService(); err != nil {
				log.Fatalf("Failed to start service: %v", err)
			}
			fmt.Println("RedFlag service started successfully")
			os.Exit(0)
		}

		if *stopServiceCmd {
			if err := service.StopService(); err != nil {
				log.Fatalf("Failed to stop service: %v", err)
			}
			fmt.Println("RedFlag service stopped successfully")
			os.Exit(0)
		}

		if *serviceStatusCmd {
			if err := service.ServiceStatus(); err != nil {
				log.Fatalf("Failed to get service status: %v", err)
			}
			os.Exit(0)
		}
	}

	// Parse tags from comma-separated string
	var tags []string
	if *tagsFlag != "" {
		tags = strings.Split(*tagsFlag, ",")
		for i, tag := range tags {
			tags[i] = strings.TrimSpace(tag)
		}
	}

	// Create CLI flags structure
	cliFlags := &config.CLIFlags{
		ServerURL:         *serverURL,
		RegistrationToken: *registrationToken,
		ProxyHTTP:         *proxyHTTP,
		ProxyHTTPS:        *proxyHTTPS,
		ProxyNoProxy:      *proxyNoProxy,
		LogLevel:          *logLevel,
		ConfigFile:        *configFile,
		Tags:              tags,
		Organization:      *organization,
		DisplayName:       *displayName,
		InsecureTLS:       *insecureTLS,
	}

	// Determine config path
	configPath := constants.GetAgentConfigPath()
	if *configFile != "" {
		configPath = *configFile
	}

	// Check for migration requirements before loading configuration
	migrationConfig := migration.NewFileDetectionConfig()
	// Set old paths to detect existing installations
	migrationConfig.OldConfigPath = constants.LegacyConfigPath
	migrationConfig.OldStatePath = constants.LegacyStatePath
	// Set new paths that agent will actually use
	migrationConfig.NewConfigPath = constants.GetAgentConfigDir()
	migrationConfig.NewStatePath = constants.GetAgentStateDir()

	// Detect migration requirements
	migrationDetection, err := migration.DetectMigrationRequirements(migrationConfig)
	if err != nil {
		log.Printf("Warning: Failed to detect migration requirements: %v", err)
	} else if migrationDetection.RequiresMigration {
		log.Printf("[RedFlag Server Migrator] Migration detected: %s → %s", migrationDetection.CurrentAgentVersion, version.Version)
		log.Printf("[RedFlag Server Migrator] Required migrations: %v", migrationDetection.RequiredMigrations)

		// Create migration plan
		migrationPlan := &migration.MigrationPlan{
			Detection:     migrationDetection,
			TargetVersion: version.Version,
			Config:        migrationConfig,
			BackupPath:    constants.GetMigrationBackupDir(), // Set backup path within agent's state directory
		}

		// Execute migration
		executor := migration.NewMigrationExecutor(migrationPlan, configPath)
		result, err := executor.ExecuteMigration()
		if err != nil {
			log.Printf("[RedFlag Server Migrator] Migration failed: %v", err)
			log.Printf("[RedFlag Server Migrator] Backup available at: %s", result.BackupPath)
			log.Printf("[RedFlag Server Migrator] Agent may not function correctly until migration is completed")
		} else {
			log.Printf("[RedFlag Server Migrator] Migration completed successfully")
			if result.RollbackAvailable {
				log.Printf("[RedFlag Server Migrator] Rollback available at: %s", result.BackupPath)
			}
		}
	}

	// Load configuration with priority: CLI > env > file > defaults
	cfg, err := config.Load(configPath, cliFlags)
	if err != nil {
		log.Fatal("Failed to load configuration:", err)
	}

	// Always set the current agent version in config
	if cfg.AgentVersion != version.Version {
		if cfg.AgentVersion != "" {
			log.Printf("[RedFlag Server Migrator] Version change detected: %s → %s", cfg.AgentVersion, version.Version)
			log.Printf("[RedFlag Server Migrator] Performing lightweight migration check...")
		}

		// Update config version to match current agent
		cfg.AgentVersion = version.Version

		// Save updated config
		if err := cfg.Save(configPath); err != nil {
			log.Printf("Warning: Failed to update agent version in config: %v", err)
		} else {
			if cfg.AgentVersion != "" {
				log.Printf("[RedFlag Server Migrator] Agent version updated in configuration")
			}
		}
	}

	// Handle registration
	if *registerCmd {
		// Validate server URL for Windows users
		if runtime.GOOS == "windows" && strings.Contains(*serverURL, "REPLACE_WITH_SERVER_IP") {
			fmt.Println("❌ CONFIGURATION REQUIRED!")
			fmt.Println("==================================================================")
			fmt.Println("Please configure the server URL before registering:")
			fmt.Println("")
			fmt.Println("Option 1 - Use the -server flag:")
			fmt.Printf("   redflag-agent.exe -register -server http://10.10.20.159:8080\n")
			fmt.Println("")
			fmt.Println("Option 2 - Use environment variable:")
			fmt.Println("   set REDFLAG_SERVER_URL=http://10.10.20.159:8080")
			fmt.Println("   redflag-agent.exe -register")
			fmt.Println("")
			fmt.Println("Option 3 - Create a .env file:")
			fmt.Println("   REDFLAG_SERVER_URL=http://10.10.20.159:8080")
			fmt.Println("==================================================================")
			os.Exit(1)
		}

		if err := registerAgent(cfg, *serverURL); err != nil {
			log.Fatal("Registration failed:", err)
		}
		fmt.Println("==================================================================")
		fmt.Println("🎉 AGENT REGISTRATION SUCCESSFUL!")
		fmt.Println("==================================================================")
		fmt.Printf("📋 Agent ID: %s\n", cfg.AgentID)
		fmt.Printf("🌐 Server: %s\n", cfg.ServerURL)
		fmt.Printf("⏱️  Check-in Interval: %ds\n", cfg.CheckInInterval)
		fmt.Println("==================================================================")
		fmt.Println("💡 Save this Agent ID for your records!")
		fmt.Println("🚀 You can now start the agent without flags")
		fmt.Println("")
		return
	}

	// Handle scan command
	if *scanCmd {
		if err := handleScanCommand(cfg, *exportFormat); err != nil {
			log.Fatal("Scan failed:", err)
		}
		return
	}

	// Handle status command
	if *statusCmd {
		if err := handleStatusCommand(cfg); err != nil {
			log.Fatal("Status command failed:", err)
		}
		return
	}

	// Handle list-updates command
	if *listUpdatesCmd {
		if err := handleListUpdatesCommand(cfg, *exportFormat); err != nil {
			log.Fatal("List updates failed:", err)
		}
		return
	}

	// Check if registered
	if !cfg.IsRegistered() {
		log.Fatal("Agent not registered. Run with -register flag first.")
	}

	// Check if running as Windows service
	if runtime.GOOS == "windows" && service.IsService() {
		// Run as Windows service
		if err := service.RunService(cfg); err != nil {
			log.Fatal("Service failed:", err)
		}
		return
	}

	// Start agent service (console mode)
	if err := runAgent(cfg); err != nil {
		log.Fatal("Agent failed:", err)
	}
}

func registerAgent(cfg *config.Config, serverURL string) error {
	// Get detailed system information
	sysInfo, err := system.GetSystemInfo(version.Version)
	if err != nil {
		log.Printf("Warning: Failed to get detailed system info: %v\n", err)
		// Fall back to basic detection
		hostname, _ := os.Hostname()
		osType, osVersion, osArch := client.DetectSystem()
		sysInfo = &system.SystemInfo{
			Hostname:       hostname,
			OSType:         osType,
			OSVersion:      osVersion,
			OSArchitecture: osArch,
			AgentVersion:   version.Version,
			Metadata:       make(map[string]string),
		}
	}

	// Use registration token from config if available
	apiClient := client.NewClient(serverURL, cfg.RegistrationToken)

	// Create metadata with system information
	metadata := map[string]string{
		"installation_time": time.Now().Format(time.RFC3339),
	}

	// Add system info to metadata
	if sysInfo.CPUInfo.ModelName != "" {
		metadata["cpu_model"] = sysInfo.CPUInfo.ModelName
	}
	if sysInfo.CPUInfo.Cores > 0 {
		metadata["cpu_cores"] = fmt.Sprintf("%d", sysInfo.CPUInfo.Cores)
	}
	if sysInfo.MemoryInfo.Total > 0 {
		metadata["memory_total"] = fmt.Sprintf("%d", sysInfo.MemoryInfo.Total)
	}
	if sysInfo.RunningProcesses > 0 {
		metadata["processes"] = fmt.Sprintf("%d", sysInfo.RunningProcesses)
	}
	if sysInfo.Uptime != "" {
		metadata["uptime"] = sysInfo.Uptime
	}

	// Add disk information
	for i, disk := range sysInfo.DiskInfo {
		if i == 0 {
			metadata["disk_mount"] = disk.Mountpoint
			metadata["disk_total"] = fmt.Sprintf("%d", disk.Total)
			metadata["disk_used"] = fmt.Sprintf("%d", disk.Used)
			break // Only add primary disk info
		}
	}

	// Get machine ID for binding (F-D1-1 fix: no unhashed fallback)
	// system.GetMachineID() has its own internal fallback chain that
	// always produces a SHA256 hash. If even that fails, abort registration.
	machineID, err := system.GetMachineID()
	if err != nil {
		log.Fatalf("[ERROR] [agent] [registration] machine_id_unavailable error=%q — cannot register without consistent machine ID", err)
	}

	// Get embedded public key fingerprint
	publicKeyFingerprint := system.GetPublicKeyFingerprint()
	if publicKeyFingerprint == "" {
		log.Printf("Warning: No embedded public key fingerprint found")
	}

	req := client.RegisterRequest{
		Hostname:             sysInfo.Hostname,
		OSType:               sysInfo.OSType,
		OSVersion:            sysInfo.OSVersion,
		OSArchitecture:       sysInfo.OSArchitecture,
		AgentVersion:         sysInfo.AgentVersion,
		MachineID:            machineID,
		PublicKeyFingerprint: publicKeyFingerprint,
		Metadata:             metadata,
	}

	resp, err := apiClient.Register(req)
	if err != nil {
		return err
	}

	// Update configuration
	cfg.ServerURL = serverURL
	cfg.AgentID = resp.AgentID
	cfg.Token = resp.Token
	cfg.RefreshToken = resp.RefreshToken

	// Get check-in interval from server config
	if interval, ok := resp.Config["check_in_interval"].(float64); ok {
		cfg.CheckInInterval = int(interval)
	} else {
		cfg.CheckInInterval = 300 // Default 5 minutes
	}

	// Save configuration
	if err := cfg.Save(constants.GetAgentConfigPath()); err != nil {
		return fmt.Errorf("failed to save config: %w", err)
	}

	// Fetch and cache server public key for signature verification
	log.Println("Fetching server public key for update signature verification...")
	if err := fetchAndCachePublicKey(cfg.ServerURL); err != nil {
		log.Printf("Warning: Failed to fetch server public key: %v", err)
		log.Printf("Agent will not be able to verify update signatures")
		// Don't fail registration - key can be fetched later
	} else {
		log.Println("[INFO] [agent] [crypto] server_public_key_cached")
	}

	return nil
}

// fetchAndCachePublicKey fetches the server's Ed25519 public key and caches it locally
func fetchAndCachePublicKey(serverURL string) error {
	_, err := crypto.FetchAndCacheServerPublicKey(serverURL)
	return err
}

// renewTokenIfNeeded handles 401 errors by renewing the agent token using refresh token
func renewTokenIfNeeded(apiClient *client.Client, cfg *config.Config, err error) (*client.Client, error) {
	if err != nil && strings.Contains(err.Error(), "401 Unauthorized") {
		log.Printf("[INFO] [agent] [auth] access_token_expired attempting_renewal")

		// Check if we have a refresh token
		if cfg.RefreshToken == "" {
			log.Printf("[ERROR] [agent] [auth] no_refresh_token re-registration_required")
			return nil, fmt.Errorf("refresh token missing - please re-register agent")
		}

		// Create temporary client without token for renewal
		tempClient := client.NewClient(cfg.ServerURL, "")

		// Attempt to renew access token using refresh token
		if err := tempClient.RenewToken(cfg.AgentID, cfg.RefreshToken, version.Version); err != nil {
			log.Printf("[ERROR] [agent] [auth] refresh_token_renewal_failed error=%v", err)
			log.Printf("[INFO] [agent] [auth] refresh_token_may_be_expired re-registration_required")
			return nil, fmt.Errorf("refresh token renewal failed: %w - please re-register agent", err)
		}

		// Update config with new access token
		cfg.Token = tempClient.GetToken()

		// Save updated config
		if err := cfg.Save(constants.GetAgentConfigPath()); err != nil {
			log.Printf("[WARNING] [agent] [auth] save_renewed_token_failed error=%v", err)
		}

		log.Printf("[INFO] [agent] [auth] access_token_renewed agent_id=%s", cfg.AgentID)
		return tempClient, nil
	}

	// Return original client if no 401 error
	return apiClient, nil
}

// getCurrentSubsystemEnabled returns the current enabled state for a subsystem
func getCurrentSubsystemEnabled(cfg *config.Config, subsystemName string) bool {
	switch subsystemName {
	case "system":
		return cfg.Subsystems.System.Enabled
	case "updates":
		return cfg.Subsystems.Updates.Enabled
	case "docker":
		return cfg.Subsystems.Docker.Enabled
	case "storage":
		return cfg.Subsystems.Storage.Enabled
	case "apt":
		return cfg.Subsystems.APT.Enabled
	case "dnf":
		return cfg.Subsystems.DNF.Enabled
	case "windows":
		return cfg.Subsystems.Windows.Enabled
	case "winget":
		return cfg.Subsystems.Winget.Enabled
	default:
		// Unknown subsystem, assume disabled
		return false
	}
}

// syncServerConfigProper checks for and applies server configuration updates with validation and protection
func syncServerConfigProper(apiClient *client.Client, cfg *config.Config) error {
	serverConfig, err := apiClient.GetConfig(cfg.AgentID)
	if err != nil {
		log.Printf("[HISTORY] [agent] [config] sync_failed error=\"%v\" timestamp=%s",
			err, time.Now().Format(time.RFC3339))
		return fmt.Errorf("failed to get server config: %w", err)
	}

	if serverConfig.Version <= lastConfigVersion {
		return nil // No update needed
	}

	log.Printf("[INFO] [agent] [config] server config update detected (version: %d)", serverConfig.Version)
	changes := false

	// Create validator for interval bounds checking
	intervalValidator := validator.NewIntervalValidator()

	// Create guardian to protect against check-in interval override attempts
	intervalGuardian := guardian.NewIntervalGuardian()
	intervalGuardian.SetBaseline(cfg.CheckInInterval)

	// Process subsystem configurations
	for subsystemName, subsystemConfig := range serverConfig.Subsystems {
		if configMap, ok := subsystemConfig.(map[string]interface{}); ok {

			// Parse interval from server config
			intervalFloat := 0.0
			if rawInterval, ok := configMap["interval_minutes"].(float64); ok {
				intervalFloat = rawInterval
			}
			intervalMinutes := int(intervalFloat)

			// Validate scanner interval
			if intervalMinutes > 0 {
				if err := intervalValidator.ValidateScannerInterval(intervalMinutes); err != nil {
					log.Printf("[ERROR] [agent] [config] [%s] scanner interval validation failed: %v",
						subsystemName, err)
					log.Printf("[HISTORY] [agent] [config] [%s] interval_rejected interval=%d reason=\"%v\" timestamp=%s",
						subsystemName, intervalMinutes, err, time.Now().Format(time.RFC3339))
					continue // Skip invalid interval but don't fail entire sync
				}

				log.Printf("[INFO] [agent] [config] [%s] interval=%d minutes", subsystemName, intervalMinutes)
				changes = true

				// Apply validated interval to the appropriate subsystem
				switch subsystemName {
				case "system":
					cfg.Subsystems.System.IntervalMinutes = intervalMinutes
				case "apt":
					cfg.Subsystems.APT.IntervalMinutes = intervalMinutes
				case "dnf":
					cfg.Subsystems.DNF.IntervalMinutes = intervalMinutes
				case "storage":
					cfg.Subsystems.Storage.IntervalMinutes = intervalMinutes
				case "winget":
					cfg.Subsystems.Winget.IntervalMinutes = intervalMinutes
				default:
					log.Printf("[WARNING] [agent] [config] unknown subsystem: %s", subsystemName)
				}

				// Log to history table
				log.Printf("[HISTORY] [agent] [config] [%s] interval_updated minutes=%d timestamp=%s",
					subsystemName, intervalMinutes, time.Now().Format(time.RFC3339))
			}
		}
	}

	// Verification: Ensure no scanner interval is interfering with check-in frequency
	// This guards against regressions where scanner settings might affect agent polling
	if intervalGuardian.GetViolationCount() > 0 {
		log.Printf("[WARNING] [agent] [config] guardian detected %d previous interval violations",
			intervalGuardian.GetViolationCount())
	}

	if err := cfg.Save(constants.GetAgentConfigPath()); err != nil {
		log.Printf("[HISTORY] [agent] [config] save_failed error=\"%v\" timestamp=%s",
			err, time.Now().Format(time.RFC3339))
		return fmt.Errorf("failed to save config: %w", err)
	}

	if changes {
		log.Printf("[INFO] [agent] [config] scanner interval updates applied")
	}

	lastConfigVersion = serverConfig.Version
	log.Printf("[SUCCESS] [agent] [config] config saved successfully")

	return nil
}

// syncServerConfigWithRetry wraps syncServerConfigProper with retry logic
func syncServerConfigWithRetry(apiClient *client.Client, cfg *config.Config, maxRetries int) error {
	var lastErr error

	for attempt := 1; attempt <= maxRetries; attempt++ {
		if err := syncServerConfigProper(apiClient, cfg); err != nil {
			lastErr = err

			log.Printf("[ERROR] [agent] [config] sync attempt %d/%d failed: %v",
				attempt, maxRetries, err)

			// Log to history table
			log.Printf("[HISTORY] [agent] [config] sync_failed attempt=%d/%d error=\"%v\" timestamp=%s",
				attempt, maxRetries, err, time.Now().Format(time.RFC3339))

			if attempt < maxRetries {
				// Exponential backoff: 1s, 2s, 4s, 8s...
				backoff := time.Duration(1<<uint(attempt-1)) * time.Second
				log.Printf("[INFO] [agent] [config] retrying in %v...", backoff)
				time.Sleep(backoff)
			}
			continue
		}

		log.Printf("[SUCCESS] [agent] [config] synced after %d attempts", attempt)
		return nil
	}

	// After maxRetries, degrade gracefully
	if err := cfg.SetDegradedMode(true); err != nil {
		log.Printf("[ERROR] [agent] [config] failed to enter degraded mode: %v", err)
		log.Printf("[HISTORY] [agent] [config] degraded_mode_failed error=\"%v\" timestamp=%s",
			err, time.Now().Format(time.RFC3339))
	} else {
		log.Printf("[WARNING] [agent] [config] entering degraded mode after %d failed attempts", maxRetries)
	}

	// Log degraded mode entry to history
	log.Printf("[HISTORY] [agent] [config] degraded_mode_entered failures=%d timestamp=%s",
		maxRetries, time.Now().Format(time.RFC3339))

	return lastErr
}

func runAgent(cfg *config.Config) error {
	log.Printf("🚩 RedFlag Agent v%s starting...\n", version.Version)
	log.Printf("==================================================================")
	log.Printf("📋 AGENT ID: %s", cfg.AgentID)
	log.Printf("🌐 SERVER: %s", cfg.ServerURL)
	log.Printf("⏱️  CHECK-IN INTERVAL: %ds", cfg.CheckInInterval)
	log.Printf("==================================================================")
	log.Printf("💡 Tip: Use this Agent ID to identify this agent in the web UI")
	log.Printf("")

	apiClient := client.NewClient(cfg.ServerURL, cfg.Token)

	// Initialize scanners for package updates (used by update orchestrator)
	aptScanner := scanner.NewAPTScanner()
	dnfScanner := scanner.NewDNFScanner()
	windowsUpdateScanner := scanner.NewWindowsUpdateScanner()
	wingetScanner := scanner.NewWingetScanner()

	// Docker, Storage, and System scanners are created by individual subsystem handlers
	// dockerScanner is created in HandleScanDocker
	// storageScanner and systemScanner are created in main for individual handlers

	// Initialize circuit breakers for update scanners only
	aptCB := circuitbreaker.New("APT", circuitbreaker.Config{
		FailureThreshold: cfg.Subsystems.APT.CircuitBreaker.FailureThreshold,
		FailureWindow:    cfg.Subsystems.APT.CircuitBreaker.FailureWindow,
		OpenDuration:     cfg.Subsystems.APT.CircuitBreaker.OpenDuration,
		HalfOpenAttempts: cfg.Subsystems.APT.CircuitBreaker.HalfOpenAttempts,
	})
	dnfCB := circuitbreaker.New("DNF", circuitbreaker.Config{
		FailureThreshold: cfg.Subsystems.DNF.CircuitBreaker.FailureThreshold,
		FailureWindow:    cfg.Subsystems.DNF.CircuitBreaker.FailureWindow,
		OpenDuration:     cfg.Subsystems.DNF.CircuitBreaker.OpenDuration,
		HalfOpenAttempts: cfg.Subsystems.DNF.CircuitBreaker.HalfOpenAttempts,
	})
	windowsCB := circuitbreaker.New("Windows Update", circuitbreaker.Config{
		FailureThreshold: cfg.Subsystems.Windows.CircuitBreaker.FailureThreshold,
		FailureWindow:    cfg.Subsystems.Windows.CircuitBreaker.FailureWindow,
		OpenDuration:     cfg.Subsystems.Windows.CircuitBreaker.OpenDuration,
		HalfOpenAttempts: cfg.Subsystems.Windows.CircuitBreaker.HalfOpenAttempts,
	})
	wingetCB := circuitbreaker.New("Winget", circuitbreaker.Config{
		FailureThreshold: cfg.Subsystems.Winget.CircuitBreaker.FailureThreshold,
		FailureWindow:    cfg.Subsystems.Winget.CircuitBreaker.FailureWindow,
		OpenDuration:     cfg.Subsystems.Winget.CircuitBreaker.OpenDuration,
		HalfOpenAttempts: cfg.Subsystems.Winget.CircuitBreaker.HalfOpenAttempts,
	})

	// Initialize scanner orchestrator for parallel execution and granular subsystem management
	scanOrchestrator := orchestrator.NewOrchestrator()

	// Initialize command handler with signature verification (ETHOS #2 - Security is Non-Negotiable)
	securityLogger, err := logging.NewSecurityLogger(cfg, constants.GetAgentStateDir())
	if err != nil {
		log.Printf("[ERROR] [agent] [cmd_handler] security_logger_init_failed error=\"%v\"", err)
		// Continue without security logger - verification still works
		securityLogger = nil
	}

	commandHandler, err := orchestrator.NewCommandHandler(cfg, securityLogger, log.New(os.Stdout, "", log.LstdFlags))
	if err != nil {
		log.Printf("[ERROR] [agent] [cmd_handler] init_failed error=\"%v\"", err)
		return fmt.Errorf("failed to initialize command handler: %w", err)
	}

	// Initialize scanners for storage, system, and docker (used by individual subsystem handlers)
	storageScanner := orchestrator.NewStorageScanner(version.Version)
	systemScanner := orchestrator.NewSystemScanner(version.Version)
	dockerScanner, _ := scanner.NewDockerScanner()

	// Initialize circuit breakers for all subsystems
	storageCB := circuitbreaker.New("Storage", circuitbreaker.Config{
		FailureThreshold: cfg.Subsystems.Storage.CircuitBreaker.FailureThreshold,
		FailureWindow:    cfg.Subsystems.Storage.CircuitBreaker.FailureWindow,
		OpenDuration:     cfg.Subsystems.Storage.CircuitBreaker.OpenDuration,
		HalfOpenAttempts: cfg.Subsystems.Storage.CircuitBreaker.HalfOpenAttempts,
	})
	systemCB := circuitbreaker.New("System", circuitbreaker.Config{
		FailureThreshold: cfg.Subsystems.System.CircuitBreaker.FailureThreshold,
		FailureWindow:    cfg.Subsystems.System.CircuitBreaker.FailureWindow,
		OpenDuration:     cfg.Subsystems.System.CircuitBreaker.OpenDuration,
		HalfOpenAttempts: cfg.Subsystems.System.CircuitBreaker.HalfOpenAttempts,
	})
	dockerCB := circuitbreaker.New("Docker", circuitbreaker.Config{
		FailureThreshold: cfg.Subsystems.Docker.CircuitBreaker.FailureThreshold,
		FailureWindow:    cfg.Subsystems.Docker.CircuitBreaker.FailureWindow,
		OpenDuration:     cfg.Subsystems.Docker.CircuitBreaker.OpenDuration,
		HalfOpenAttempts: cfg.Subsystems.Docker.CircuitBreaker.HalfOpenAttempts,
	})

	// Register ALL scanners with the orchestrator
	// Update scanners (package management)
	scanOrchestrator.RegisterScanner("apt", orchestrator.NewAPTScannerWrapper(aptScanner), aptCB, cfg.Subsystems.APT.Timeout, cfg.Subsystems.APT.Enabled)
	scanOrchestrator.RegisterScanner("dnf", orchestrator.NewDNFScannerWrapper(dnfScanner), dnfCB, cfg.Subsystems.DNF.Timeout, cfg.Subsystems.DNF.Enabled)
	scanOrchestrator.RegisterScanner("windows", orchestrator.NewWindowsUpdateScannerWrapper(windowsUpdateScanner), windowsCB, cfg.Subsystems.Windows.Timeout, cfg.Subsystems.Windows.Enabled)
	scanOrchestrator.RegisterScanner("winget", orchestrator.NewWingetScannerWrapper(wingetScanner), wingetCB, cfg.Subsystems.Winget.Timeout, cfg.Subsystems.Winget.Enabled)

	// System scanners (metrics and monitoring)
	scanOrchestrator.RegisterScanner("storage", orchestrator.NewStorageScannerWrapper(storageScanner), storageCB, cfg.Subsystems.Storage.Timeout, cfg.Subsystems.Storage.Enabled)
	scanOrchestrator.RegisterScanner("system", orchestrator.NewSystemScannerWrapper(systemScanner), systemCB, cfg.Subsystems.System.Timeout, cfg.Subsystems.System.Enabled)
	scanOrchestrator.RegisterScanner("docker", orchestrator.NewDockerScannerWrapper(dockerScanner), dockerCB, cfg.Subsystems.Docker.Timeout, cfg.Subsystems.Docker.Enabled)

	// Initialize acknowledgment tracker for command result reliability
	ackTracker := acknowledgment.NewTracker(constants.GetAgentStateDir())
	if err := ackTracker.Load(); err != nil {
		log.Printf("Warning: Failed to load pending acknowledgments: %v", err)
	} else {
		pendingCount := len(ackTracker.GetPending())
		if pendingCount > 0 {
			log.Printf("Loaded %d pending command acknowledgments from previous session", pendingCount)
		}
	}

	// Periodic cleanup of old/stale acknowledgments
	go func() {
		cleanupTicker := time.NewTicker(1 * time.Hour)
		defer cleanupTicker.Stop()
		for range cleanupTicker.C {
			removed := ackTracker.Cleanup()
			if removed > 0 {
				log.Printf("Cleaned up %d stale acknowledgments", removed)
				if err := ackTracker.Save(); err != nil {
					log.Printf("Warning: Failed to save acknowledgments after cleanup: %v", err)
				}
			}
		}
	}()

	// System info tracking
	var lastSystemInfoUpdate time.Time
	const systemInfoUpdateInterval = 1 * time.Hour // Update detailed system info every hour

	// Main check-in loop
	consecutiveFailures := 0 // For exponential backoff (F-B2-7)
	for {
		// F-B2-5 fix: Cap jitter at half the polling interval to preserve rapid mode
		pollingInterval := time.Duration(getCurrentPollingInterval(cfg)) * time.Second
		maxJitter := pollingInterval / 2
		if maxJitter > 30*time.Second {
			maxJitter = 30 * time.Second
		}
		if maxJitter < 1*time.Second {
			maxJitter = 1 * time.Second
		}
		jitter := time.Duration(rand.Intn(int(maxJitter.Seconds())+1)) * time.Second
		time.Sleep(jitter)

		// Check if we need to send detailed system info update
		if time.Since(lastSystemInfoUpdate) >= systemInfoUpdateInterval {
			log.Printf("Updating detailed system information...")
			if err := reportSystemInfo(apiClient, cfg); err != nil {
				log.Printf("Failed to report system info: %v\n", err)
			} else {
				lastSystemInfoUpdate = time.Now()
				log.Printf("[INFO] [agent] [installer]System information updated\n")
			}
		}

		// Proactively refresh the server's public key every 6 hours
		if commandHandler.ShouldRefreshKey() {
			if err := commandHandler.RefreshPrimaryKey(cfg.ServerURL); err != nil {
				log.Printf("[WARNING] [agent] [key_refresh] failed to refresh public key: %v", err)
			}
			// F-2 fix: clean up expired entries from the executed command dedup set
			commandHandler.CleanupExecutedIDs()
		}

		log.Printf("Checking in with server... (Agent v%s)", version.Version)

		// Collect lightweight system metrics
		sysMetrics, err := system.GetLightweightMetrics()
		var metrics *client.SystemMetrics
		if err == nil {
			metrics = &client.SystemMetrics{
				CPUPercent:    sysMetrics.CPUPercent,
				MemoryPercent: sysMetrics.MemoryPercent,
				MemoryUsedGB:  sysMetrics.MemoryUsedGB,
				MemoryTotalGB: sysMetrics.MemoryTotalGB,
				DiskUsedGB:    sysMetrics.DiskUsedGB,
				DiskTotalGB:   sysMetrics.DiskTotalGB,
				DiskPercent:   sysMetrics.DiskPercent,
				Uptime:        sysMetrics.Uptime,
				Version:       version.Version,
			}
		}

		// Add heartbeat status to metrics metadata if available
		if metrics != nil && cfg.RapidPollingEnabled {
			// Check if rapid polling is still valid
			if time.Now().Before(cfg.RapidPollingUntil) {
				// Include heartbeat metadata in metrics
				if metrics.Metadata == nil {
					metrics.Metadata = make(map[string]interface{})
				}
				metrics.Metadata["rapid_polling_enabled"] = true
				metrics.Metadata["rapid_polling_until"] = cfg.RapidPollingUntil.Format(time.RFC3339)
				metrics.Metadata["rapid_polling_duration_minutes"] = int(time.Until(cfg.RapidPollingUntil).Minutes())
			} else {
				// Heartbeat expired, disable it
				cfg.RapidPollingEnabled = false
				cfg.RapidPollingUntil = time.Time{}
			}
		}

		// Add pending acknowledgments to metrics for reliability
		if metrics != nil {
			pendingAcks := ackTracker.GetPending()
			if len(pendingAcks) > 0 {
				metrics.PendingAcknowledgments = pendingAcks
				log.Printf("Including %d pending acknowledgments in check-in: %v", len(pendingAcks), pendingAcks)
			} else {
				log.Printf("No pending acknowledgments to send")
			}
		} else {
			log.Printf("Metrics is nil - not sending system information or acknowledgments")
		}

		// Get commands from server (with optional metrics)
		response, err := apiClient.GetCommands(cfg.AgentID, metrics)
		if err != nil {
			// Try to renew token if we got a 401 error
			newClient, renewErr := renewTokenIfNeeded(apiClient, cfg, err)
			if renewErr != nil {
				consecutiveFailures++
				backoffDelay := calculateBackoff(consecutiveFailures)
				log.Printf("[WARNING] [agent] [polling] server_unavailable attempt=%d next_retry_in=%s error=%q", consecutiveFailures, backoffDelay, renewErr)
				time.Sleep(backoffDelay)
				continue
			}

			// If token was renewed, update client and retry
			if newClient != apiClient {
				log.Printf("[INFO] [agent] [polling] retrying_with_renewed_token")
				apiClient = newClient
				response, err = apiClient.GetCommands(cfg.AgentID, metrics)
				if err != nil {
					consecutiveFailures++
					backoffDelay := calculateBackoff(consecutiveFailures)
					log.Printf("[WARNING] [agent] [polling] server_unavailable attempt=%d next_retry_in=%s error=%q", consecutiveFailures, backoffDelay, err)
					time.Sleep(backoffDelay)
					continue
				}
			} else {
				consecutiveFailures++
				backoffDelay := calculateBackoff(consecutiveFailures)
				log.Printf("[WARNING] [agent] [polling] server_unavailable attempt=%d next_retry_in=%s error=%q", consecutiveFailures, backoffDelay, err)
				time.Sleep(backoffDelay)
				continue
			}
		}
		// Reset consecutive failures on success
		consecutiveFailures = 0

		// Process acknowledged command results
		if response != nil && len(response.AcknowledgedIDs) > 0 {
			ackTracker.Acknowledge(response.AcknowledgedIDs)
			log.Printf("Server acknowledged %d command result(s)", len(response.AcknowledgedIDs))

			// Save acknowledgment state
			if err := ackTracker.Save(); err != nil {
				log.Printf("Warning: Failed to save acknowledgment state: %v", err)
			}
		}

		// Sync configuration from server (non-blocking) with retry logic
		go func() {
			if err := syncServerConfigWithRetry(apiClient, cfg, 5); err != nil {
				log.Printf("Warning: Failed to sync server config after retries: %v", err)
			}
		}()

		commands := response.Commands
		if len(commands) == 0 {
			log.Printf("Check-in successful - no new commands")
		} else {
			log.Printf("Check-in successful - received %d command(s)", len(commands))
		}

		// Process each command
		for _, cmd := range commands {
			log.Printf("Processing command: %s (%s)\n", cmd.Type, cmd.ID)

			// Verify command signature before execution (ETHOS #2 - Security is Non-Negotiable)
			if err := commandHandler.ProcessCommand(cmd, cfg, cfg.AgentID); err != nil {
				// Verification failed - log and report to server, then skip command
				log.Printf("[ERROR] [agent] [cmd_verify] command_rejected command_id=%s reason=\"%s\"", cmd.ID, err.Error())

				// Report verification failure to server with acknowledgment tracking
				logReport := client.LogReport{
					CommandID:       cmd.ID,
					Action:          "verify_command",
					Result:          "failed",
					Stdout:          "",
					Stderr:          fmt.Sprintf("Command verification failed: %s", err.Error()),
					ExitCode:        1,
					DurationSeconds: 0,
				}
				if reportErr := reportLogWithAck(apiClient, cfg, ackTracker, logReport); reportErr != nil {
					log.Printf("[ERROR] [agent] [cmd_verify] report_failed error=\"%v\"", reportErr)
				}

				// Continue to next command - DO NOT execute
				continue
			}

			switch cmd.Type {
			case "scan_storage":
				if err := handlers.HandleScanStorage(apiClient, cfg, ackTracker, scanOrchestrator, cmd.ID); err != nil {
					log.Printf("Error scanning storage: %v\n", err)
				}

			case "scan_system":
				if err := handlers.HandleScanSystem(apiClient, cfg, ackTracker, scanOrchestrator, cmd.ID); err != nil {
					log.Printf("Error scanning system: %v\n", err)
				}

			case "scan_docker":
				if err := handlers.HandleScanDocker(apiClient, cfg, ackTracker, scanOrchestrator, cmd.ID); err != nil {
					log.Printf("Error scanning Docker: %v\n", err)
				}

			case "scan_apt":
				if err := handlers.HandleScanAPT(apiClient, cfg, ackTracker, scanOrchestrator, cmd.ID); err != nil {
					log.Printf("Error scanning APT: %v\n", err)
				}

			case "scan_dnf":
				if err := handlers.HandleScanDNF(apiClient, cfg, ackTracker, scanOrchestrator, cmd.ID); err != nil {
					log.Printf("Error scanning DNF: %v\n", err)
				}

			case "scan_windows":
				if err := handlers.HandleScanWindows(apiClient, cfg, ackTracker, scanOrchestrator, cmd.ID); err != nil {
					log.Printf("Error scanning Windows Updates: %v\n", err)
				}

			case "scan_winget":
				if err := handlers.HandleScanWinget(apiClient, cfg, ackTracker, scanOrchestrator, cmd.ID); err != nil {
					log.Printf("Error scanning Winget: %v\n", err)
				}

			case "collect_specs":
				log.Println("Spec collection not yet implemented")

			case "dry_run_update":
				if err := handleDryRunUpdate(apiClient, cfg, ackTracker, cmd.ID, cmd.Params); err != nil {
					log.Printf("Error dry running update: %v\n", err)
				}

			case "install_updates":
				if err := handleInstallUpdates(apiClient, cfg, ackTracker, cmd.ID, cmd.Params); err != nil {
					log.Printf("Error installing updates: %v\n", err)
				}

			case "confirm_dependencies":
				if err := handleConfirmDependencies(apiClient, cfg, ackTracker, cmd.ID, cmd.Params); err != nil {
					log.Printf("Error confirming dependencies: %v\n", err)
				}

			case "enable_heartbeat":
				if err := handleEnableHeartbeat(apiClient, cfg, ackTracker, cmd.ID, cmd.Params); err != nil {
					log.Printf("[Heartbeat] Error enabling heartbeat: %v\n", err)
				}

			case "disable_heartbeat":
				if err := handleDisableHeartbeat(apiClient, cfg, ackTracker, cmd.ID); err != nil {
					log.Printf("[Heartbeat] Error disabling heartbeat: %v\n", err)
				}

			case "reboot":
				if err := handleReboot(apiClient, cfg, ackTracker, cmd.ID, cmd.Params); err != nil {
					log.Printf("[Reboot] Error processing reboot command: %v\n", err)
				}

			case "update_agent":
				if err := handleUpdateAgent(apiClient, cfg, ackTracker, cmd.Params, cmd.ID); err != nil {
					log.Printf("[Update] Error processing agent update command: %v\n", err)
				}

			default:
				log.Printf("Unknown command type: %s - reporting as invalid command\n", cmd.Type)
				// Report invalid command back to server
				logReport := client.LogReport{
					CommandID:       cmd.ID,
					Action:          "process_command",
					Result:          "failed",
					Stdout:          "",
					Stderr:          fmt.Sprintf("Invalid command type: %s", cmd.Type),
					ExitCode:        1,
					DurationSeconds: 0,
				}
				if reportErr := reportLogWithAck(apiClient, cfg, ackTracker, logReport); reportErr != nil {
					log.Printf("Failed to report invalid command result: %v", reportErr)
				}
			}
		}

		// Wait for next check-in
		time.Sleep(time.Duration(getCurrentPollingInterval(cfg)) * time.Second)
	}
}

// subsystemScan executes a scanner function with circuit breaker and timeout protection
func subsystemScan(name string, cb *circuitbreaker.CircuitBreaker, timeout time.Duration, scanFn func() ([]client.UpdateReportItem, error)) ([]client.UpdateReportItem, error) {
	var updates []client.UpdateReportItem
	var scanErr error

	err := cb.Call(func() error {
		ctx, cancel := context.WithTimeout(context.Background(), timeout)
		defer cancel()

		type result struct {
			updates []client.UpdateReportItem
			err     error
		}
		resultChan := make(chan result, 1)

		go func() {
			u, e := scanFn()
			resultChan <- result{u, e}
		}()

		select {
		case <-ctx.Done():
			return fmt.Errorf("%s scan timeout after %v", name, timeout)
		case res := <-resultChan:
			if res.err != nil {
				return res.err
			}
			updates = res.updates
			return nil
		}
	})

	if err != nil {
		scanErr = err
	}

	return updates, scanErr
}

// handleScanCommand performs a local scan and displays results
func handleScanCommand(cfg *config.Config, exportFormat string) error {
	// Initialize scanners
	aptScanner := scanner.NewAPTScanner()
	dnfScanner := scanner.NewDNFScanner()
	dockerScanner, _ := scanner.NewDockerScanner()
	windowsUpdateScanner := scanner.NewWindowsUpdateScanner()
	wingetScanner := scanner.NewWingetScanner()

	fmt.Println("🔍 Scanning for updates...")
	var allUpdates []client.UpdateReportItem

	// Scan APT updates
	if aptScanner.IsAvailable() {
		fmt.Println("  - Scanning APT packages...")
		updates, err := aptScanner.Scan()
		if err != nil {
			fmt.Printf("    ⚠️  APT scan failed: %v\n", err)
		} else {
			fmt.Printf("    ✓ Found %d APT updates\n", len(updates))
			allUpdates = append(allUpdates, updates...)
		}
	}

	// Scan DNF updates
	if dnfScanner.IsAvailable() {
		fmt.Println("  - Scanning DNF packages...")
		updates, err := dnfScanner.Scan()
		if err != nil {
			fmt.Printf("    ⚠️  DNF scan failed: %v\n", err)
		} else {
			fmt.Printf("    ✓ Found %d DNF updates\n", len(updates))
			allUpdates = append(allUpdates, updates...)
		}
	}

	// Scan Docker updates
	if dockerScanner != nil && dockerScanner.IsAvailable() {
		fmt.Println("  - Scanning Docker images...")
		updates, err := dockerScanner.Scan()
		if err != nil {
			fmt.Printf("    ⚠️  Docker scan failed: %v\n", err)
		} else {
			fmt.Printf("    ✓ Found %d Docker image updates\n", len(updates))
			allUpdates = append(allUpdates, updates...)
		}
	}

	// Scan Windows updates
	if windowsUpdateScanner.IsAvailable() {
		fmt.Println("  - Scanning Windows updates...")
		updates, err := windowsUpdateScanner.Scan()
		if err != nil {
			fmt.Printf("    ⚠️  Windows Update scan failed: %v\n", err)
		} else {
			fmt.Printf("    ✓ Found %d Windows updates\n", len(updates))
			allUpdates = append(allUpdates, updates...)
		}
	}

	// Scan Winget packages
	if wingetScanner.IsAvailable() {
		fmt.Println("  - Scanning Winget packages...")
		updates, err := wingetScanner.Scan()
		if err != nil {
			fmt.Printf("    ⚠️  Winget scan failed: %v\n", err)
		} else {
			fmt.Printf("    ✓ Found %d Winget package updates\n", len(updates))
			allUpdates = append(allUpdates, updates...)
		}
	}

	// Load and update cache
	localCache, err := cache.Load()
	if err != nil {
		fmt.Printf("⚠️  Warning: Failed to load cache: %v\n", err)
		localCache = &cache.LocalCache{}
	}

	// Update cache with scan results
	localCache.UpdateScanResults(allUpdates)
	if cfg.IsRegistered() {
		localCache.SetAgentInfo(cfg.AgentID, cfg.ServerURL)
		localCache.SetAgentStatus("online")
	}

	// Save cache
	if err := localCache.Save(); err != nil {
		fmt.Printf("⚠️  Warning: Failed to save cache: %v\n", err)
	}

	// Display results
	fmt.Println()
	return display.PrintScanResults(allUpdates, exportFormat)
}

// handleStatusCommand displays agent status information
func handleStatusCommand(cfg *config.Config) error {
	// Load cache
	localCache, err := cache.Load()
	if err != nil {
		return fmt.Errorf("failed to load cache: %w", err)
	}

	// Determine status
	agentStatus := "offline"
	if cfg.IsRegistered() {
		agentStatus = "online"
	}
	if localCache.AgentStatus != "" {
		agentStatus = localCache.AgentStatus
	}

	// Use cached info if available, otherwise use config
	agentID := cfg.AgentID.String()
	if localCache.AgentID != (uuid.UUID{}) {
		agentID = localCache.AgentID.String()
	}

	serverURL := cfg.ServerURL
	if localCache.ServerURL != "" {
		serverURL = localCache.ServerURL
	}

	// Display status
	display.PrintAgentStatus(
		agentID,
		serverURL,
		localCache.LastCheckIn,
		localCache.LastScanTime,
		localCache.UpdateCount,
		agentStatus,
	)

	return nil
}

// handleListUpdatesCommand displays detailed update information
func handleListUpdatesCommand(cfg *config.Config, exportFormat string) error {
	// Load cache
	localCache, err := cache.Load()
	if err != nil {
		return fmt.Errorf("failed to load cache: %w", err)
	}

	// Check if we have cached scan results
	if len(localCache.Updates) == 0 {
		fmt.Println("📋 No cached scan results found.")
		fmt.Println("💡 Run '--scan' first to discover available updates.")
		return nil
	}

	// Warn if cache is old
	if localCache.IsExpired(24 * time.Hour) {
		fmt.Printf("⚠️  Scan results are %s old. Run '--scan' for latest results.\n\n",
			formatTimeSince(localCache.LastScanTime))
	}

	// Display detailed results
	return display.PrintDetailedUpdates(localCache.Updates, exportFormat)
}

// handleInstallUpdates handles install_updates command
func handleInstallUpdates(apiClient *client.Client, cfg *config.Config, ackTracker *acknowledgment.Tracker, commandID string, params map[string]interface{}) error {
	log.Println("Installing updates...")

	// Parse parameters
	packageType := ""
	packageName := ""

	if pt, ok := params["package_type"].(string); ok {
		packageType = pt
	}
	if pn, ok := params["package_name"].(string); ok {
		packageName = pn
	}

	// Validate package type
	if packageType == "" {
		return fmt.Errorf("package_type parameter is required")
	}

	// Create installer based on package type
	inst, err := installer.InstallerFactory(packageType)
	if err != nil {
		return fmt.Errorf("failed to create installer for package type %s: %w", packageType, err)
	}

	// Check if installer is available
	if !inst.IsAvailable() {
		return fmt.Errorf("%s installer is not available on this system", packageType)
	}

	var result *installer.InstallResult
	var action string

	// Perform installation based on what's specified
	if packageName != "" {
		action = "update"
		log.Printf("Updating package: %s (type: %s)", packageName, packageType)
		result, err = inst.UpdatePackage(packageName)
	} else if len(params) > 1 {
		// Multiple packages might be specified in various ways
		var packageNames []string
		for key, value := range params {
			if key != "package_type" {
				if name, ok := value.(string); ok && name != "" {
					packageNames = append(packageNames, name)
				}
			}
		}
		if len(packageNames) > 0 {
			action = "install_multiple"
			log.Printf("Installing multiple packages: %v (type: %s)", packageNames, packageType)
			result, err = inst.InstallMultiple(packageNames)
		} else {
			// Upgrade all packages if no specific packages named
			action = "upgrade"
			log.Printf("Upgrading all packages (type: %s)", packageType)
			result, err = inst.Upgrade()
		}
	} else {
		// Upgrade all packages if no specific packages named
		action = "upgrade"
		log.Printf("Upgrading all packages (type: %s)", packageType)
		result, err = inst.Upgrade()
	}

	if err != nil {
		// Report installation failure with actual command output
		logReport := client.LogReport{
			CommandID:       commandID,
			Action:          action,
			Result:          "failed",
			Stdout:          result.Stdout,
			Stderr:          result.Stderr,
			ExitCode:        result.ExitCode,
			DurationSeconds: result.DurationSeconds,
		}

		if reportErr := reportLogWithAck(apiClient, cfg, ackTracker, logReport); reportErr != nil {
			log.Printf("Failed to report installation failure: %v\n", reportErr)
		}

		return fmt.Errorf("installation failed: %w", err)
	}

	// Report installation success
	logReport := client.LogReport{
		CommandID:       commandID,
		Action:          result.Action,
		Result:          "success",
		Stdout:          result.Stdout,
		Stderr:          result.Stderr,
		ExitCode:        result.ExitCode,
		DurationSeconds: result.DurationSeconds,
	}

	// Add additional metadata to the log report
	if len(result.PackagesInstalled) > 0 {
		logReport.Stdout += fmt.Sprintf("\nPackages installed: %v", result.PackagesInstalled)
	}

	if reportErr := reportLogWithAck(apiClient, cfg, ackTracker, logReport); reportErr != nil {
		log.Printf("Failed to report installation success: %v\n", reportErr)
	}

	if result.Success {
		log.Printf("[INFO] [agent] [installer]Installation completed successfully in %d seconds\n", result.DurationSeconds)
		if len(result.PackagesInstalled) > 0 {
			log.Printf("  Packages installed: %v\n", result.PackagesInstalled)
		}
	} else {
		log.Printf("[ERROR] [agent] [installer]Installation failed after %d seconds\n", result.DurationSeconds)
		log.Printf("  Error: %s\n", result.ErrorMessage)
	}

	return nil
}

// handleDryRunUpdate handles dry_run_update command
func handleDryRunUpdate(apiClient *client.Client, cfg *config.Config, ackTracker *acknowledgment.Tracker, commandID string, params map[string]interface{}) error {
	log.Println("Performing dry run update...")

	// Parse parameters
	packageType := ""
	packageName := ""

	if pt, ok := params["package_type"].(string); ok {
		packageType = pt
	}
	if pn, ok := params["package_name"].(string); ok {
		packageName = pn
	}

	// Validate parameters
	if packageType == "" || packageName == "" {
		return fmt.Errorf("package_type and package_name parameters are required")
	}

	// Create installer based on package type
	inst, err := installer.InstallerFactory(packageType)
	if err != nil {
		return fmt.Errorf("failed to create installer for package type %s: %w", packageType, err)
	}

	// Check if installer is available
	if !inst.IsAvailable() {
		return fmt.Errorf("%s installer is not available on this system", packageType)
	}

	// Perform dry run
	log.Printf("Dry running package: %s (type: %s)", packageName, packageType)
	result, err := inst.DryRun(packageName)
	if err != nil {
		// Report dry run failure
		logReport := client.LogReport{
			CommandID:       commandID,
			Action:          "dry_run",
			Result:          "failed",
			Stdout:          "",
			Stderr:          fmt.Sprintf("Dry run error: %v", err),
			ExitCode:        1,
			DurationSeconds: 0,
		}

		if reportErr := reportLogWithAck(apiClient, cfg, ackTracker, logReport); reportErr != nil {
			log.Printf("Failed to report dry run failure: %v\n", reportErr)
		}

		return fmt.Errorf("dry run failed: %w", err)
	}

	// Convert installer.InstallResult to client.InstallResult for reporting
	clientResult := &client.InstallResult{
		Success:           result.Success,
		ErrorMessage:      result.ErrorMessage,
		Stdout:            result.Stdout,
		Stderr:            result.Stderr,
		ExitCode:          result.ExitCode,
		DurationSeconds:   result.DurationSeconds,
		Action:            result.Action,
		PackagesInstalled: result.PackagesInstalled,
		ContainersUpdated: result.ContainersUpdated,
		Dependencies:      result.Dependencies,
		IsDryRun:          true,
	}

	// Report dependencies back to server
	depReport := client.DependencyReport{
		PackageName:  packageName,
		PackageType:  packageType,
		Dependencies: result.Dependencies,
		UpdateID:     params["update_id"].(string),
		DryRunResult: clientResult,
	}

	if reportErr := apiClient.ReportDependencies(cfg.AgentID, depReport); reportErr != nil {
		log.Printf("Failed to report dependencies: %v\n", reportErr)
		return fmt.Errorf("failed to report dependencies: %w", reportErr)
	}

	// Report dry run success
	logReport := client.LogReport{
		CommandID:       commandID,
		Action:          "dry_run",
		Result:          "success",
		Stdout:          result.Stdout,
		Stderr:          result.Stderr,
		ExitCode:        result.ExitCode,
		DurationSeconds: result.DurationSeconds,
	}

	if len(result.Dependencies) > 0 {
		logReport.Stdout += fmt.Sprintf("\nDependencies found: %v", result.Dependencies)
	}

	if reportErr := reportLogWithAck(apiClient, cfg, ackTracker, logReport); reportErr != nil {
		log.Printf("Failed to report dry run success: %v\n", reportErr)
	}

	if result.Success {
		log.Printf("[INFO] [agent] [installer]Dry run completed successfully in %d seconds\n", result.DurationSeconds)
		if len(result.Dependencies) > 0 {
			log.Printf("  Dependencies found: %v\n", result.Dependencies)
		} else {
			log.Printf("  No additional dependencies found\n")
		}
	} else {
		log.Printf("[ERROR] [agent] [installer]Dry run failed after %d seconds\n", result.DurationSeconds)
		log.Printf("  Error: %s\n", result.ErrorMessage)
	}

	return nil
}

// handleConfirmDependencies handles confirm_dependencies command
func handleConfirmDependencies(apiClient *client.Client, cfg *config.Config, ackTracker *acknowledgment.Tracker, commandID string, params map[string]interface{}) error {
	log.Println("Installing update with confirmed dependencies...")

	// Parse parameters
	packageType := ""
	packageName := ""
	var dependencies []string

	if pt, ok := params["package_type"].(string); ok {
		packageType = pt
	}
	if pn, ok := params["package_name"].(string); ok {
		packageName = pn
	}
	if deps, ok := params["dependencies"].([]interface{}); ok {
		for _, dep := range deps {
			if depStr, ok := dep.(string); ok {
				dependencies = append(dependencies, depStr)
			}
		}
	}

	// Validate parameters
	if packageType == "" || packageName == "" {
		return fmt.Errorf("package_type and package_name parameters are required")
	}

	// Create installer based on package type
	inst, err := installer.InstallerFactory(packageType)
	if err != nil {
		return fmt.Errorf("failed to create installer for package type %s: %w", packageType, err)
	}

	// Check if installer is available
	if !inst.IsAvailable() {
		return fmt.Errorf("%s installer is not available on this system", packageType)
	}

	var result *installer.InstallResult
	var action string

	// Perform installation with dependencies
	if len(dependencies) > 0 {
		action = "install_with_dependencies"
		log.Printf("Installing package with dependencies: %s (dependencies: %v)", packageName, dependencies)
		// Install main package + dependencies
		allPackages := append([]string{packageName}, dependencies...)
		result, err = inst.InstallMultiple(allPackages)
	} else {
		action = "upgrade"
		log.Printf("Installing package: %s (no dependencies)", packageName)
		// Use UpdatePackage instead of Install to handle existing packages
		result, err = inst.UpdatePackage(packageName)
	}

	if err != nil {
		// Report installation failure with actual command output
		logReport := client.LogReport{
			CommandID:       commandID,
			Action:          action,
			Result:          "failed",
			Stdout:          result.Stdout,
			Stderr:          result.Stderr,
			ExitCode:        result.ExitCode,
			DurationSeconds: result.DurationSeconds,
		}

		if reportErr := reportLogWithAck(apiClient, cfg, ackTracker, logReport); reportErr != nil {
			log.Printf("Failed to report installation failure: %v\n", reportErr)
		}

		return fmt.Errorf("installation failed: %w", err)
	}

	// Report installation success
	logReport := client.LogReport{
		CommandID:       commandID,
		Action:          result.Action,
		Result:          "success",
		Stdout:          result.Stdout,
		Stderr:          result.Stderr,
		ExitCode:        result.ExitCode,
		DurationSeconds: result.DurationSeconds,
	}

	// Add additional metadata to the log report
	if len(result.PackagesInstalled) > 0 {
		logReport.Stdout += fmt.Sprintf("\nPackages installed: %v", result.PackagesInstalled)
	}
	if len(dependencies) > 0 {
		logReport.Stdout += fmt.Sprintf("\nDependencies included: %v", dependencies)
	}

	if reportErr := reportLogWithAck(apiClient, cfg, ackTracker, logReport); reportErr != nil {
		log.Printf("Failed to report installation success: %v\n", reportErr)
	}

	if result.Success {
		log.Printf("[INFO] [agent] [installer]Installation with dependencies completed successfully in %d seconds\n", result.DurationSeconds)
		if len(result.PackagesInstalled) > 0 {
			log.Printf("  Packages installed: %v\n", result.PackagesInstalled)
		}
	} else {
		log.Printf("[ERROR] [agent] [installer]Installation with dependencies failed after %d seconds\n", result.DurationSeconds)
		log.Printf("  Error: %s\n", result.ErrorMessage)
	}

	return nil
}

// handleEnableHeartbeat handles enable_heartbeat command
func handleEnableHeartbeat(apiClient *client.Client, cfg *config.Config, ackTracker *acknowledgment.Tracker, commandID string, params map[string]interface{}) error {
	// Parse duration parameter (default to 10 minutes)
	durationMinutes := 10
	if duration, ok := params["duration_minutes"]; ok {
		if durationFloat, ok := duration.(float64); ok {
			durationMinutes = int(durationFloat)
		}
	}

	// Calculate when heartbeat should expire
	expiryTime := time.Now().Add(time.Duration(durationMinutes) * time.Minute)

	log.Printf("[Heartbeat] Enabling rapid polling for %d minutes (expires: %s)", durationMinutes, expiryTime.Format(time.RFC3339))

	// Update agent config to enable rapid polling
	cfg.RapidPollingEnabled = true
	cfg.RapidPollingUntil = expiryTime

	// Save config to persist heartbeat settings
	if err := cfg.Save(constants.GetAgentConfigPath()); err != nil {
		log.Printf("[Heartbeat] Warning: Failed to save config: %v", err)
	}

	// Create log report for heartbeat enable
	logReport := client.LogReport{
		CommandID:       commandID,
		Action:          "enable_heartbeat",
		Result:          "success",
		Stdout:          fmt.Sprintf("Heartbeat enabled for %d minutes", durationMinutes),
		Stderr:          "",
		ExitCode:        0,
		DurationSeconds: 0,
	}

	if reportErr := reportLogWithAck(apiClient, cfg, ackTracker, logReport); reportErr != nil {
		log.Printf("[Heartbeat] Failed to report heartbeat enable: %v", reportErr)
	}

	// Send immediate check-in to update heartbeat status in UI
	log.Printf("[Heartbeat] Sending immediate check-in to update status")
	sysMetrics, err := system.GetLightweightMetrics()
	if err == nil {
		metrics := &client.SystemMetrics{
			CPUPercent:    sysMetrics.CPUPercent,
			MemoryPercent: sysMetrics.MemoryPercent,
			MemoryUsedGB:  sysMetrics.MemoryUsedGB,
			MemoryTotalGB: sysMetrics.MemoryTotalGB,
			DiskUsedGB:    sysMetrics.DiskUsedGB,
			DiskTotalGB:   sysMetrics.DiskTotalGB,
			DiskPercent:   sysMetrics.DiskPercent,
			Uptime:        sysMetrics.Uptime,
			Version:       version.Version,
		}
		// Include heartbeat metadata to show enabled state
		metrics.Metadata = map[string]interface{}{
			"rapid_polling_enabled": true,
			"rapid_polling_until":   expiryTime.Format(time.RFC3339),
		}

		// Send immediate check-in with updated heartbeat status
		_, checkinErr := apiClient.GetCommands(cfg.AgentID, metrics)
		if checkinErr != nil {
			log.Printf("[Heartbeat] Failed to send immediate check-in: %v", checkinErr)
		} else {
			log.Printf("[Heartbeat] Immediate check-in sent successfully")
		}
	} else {
		log.Printf("[Heartbeat] Failed to get system metrics for immediate check-in: %v", err)
	}

	log.Printf("[Heartbeat] Rapid polling enabled successfully")
	return nil
}

// handleDisableHeartbeat handles disable_heartbeat command
func handleDisableHeartbeat(apiClient *client.Client, cfg *config.Config, ackTracker *acknowledgment.Tracker, commandID string) error {
	log.Printf("[Heartbeat] Disabling rapid polling")

	// Update agent config to disable rapid polling
	cfg.RapidPollingEnabled = false
	cfg.RapidPollingUntil = time.Time{} // Zero value

	// Save config to persist heartbeat settings
	if err := cfg.Save(constants.GetAgentConfigPath()); err != nil {
		log.Printf("[Heartbeat] Warning: Failed to save config: %v", err)
	}

	// Create log report for heartbeat disable
	logReport := client.LogReport{
		CommandID:       commandID,
		Action:          "disable_heartbeat",
		Result:          "success",
		Stdout:          "Heartbeat disabled",
		Stderr:          "",
		ExitCode:        0,
		DurationSeconds: 0,
	}

	if reportErr := reportLogWithAck(apiClient, cfg, ackTracker, logReport); reportErr != nil {
		log.Printf("[Heartbeat] Failed to report heartbeat disable: %v", reportErr)
	}

	// Send immediate check-in to update heartbeat status in UI
	log.Printf("[Heartbeat] Sending immediate check-in to update status")
	sysMetrics, err := system.GetLightweightMetrics()
	if err == nil {
		metrics := &client.SystemMetrics{
			CPUPercent:    sysMetrics.CPUPercent,
			MemoryPercent: sysMetrics.MemoryPercent,
			MemoryUsedGB:  sysMetrics.MemoryUsedGB,
			MemoryTotalGB: sysMetrics.MemoryTotalGB,
			DiskUsedGB:    sysMetrics.DiskUsedGB,
			DiskTotalGB:   sysMetrics.DiskTotalGB,
			DiskPercent:   sysMetrics.DiskPercent,
			Uptime:        sysMetrics.Uptime,
			Version:       version.Version,
		}
		// Include empty heartbeat metadata to explicitly show disabled state
		metrics.Metadata = map[string]interface{}{
			"rapid_polling_enabled": false,
			"rapid_polling_until":   "",
		}

		// Send immediate check-in with updated heartbeat status
		_, checkinErr := apiClient.GetCommands(cfg.AgentID, metrics)
		if checkinErr != nil {
			log.Printf("[Heartbeat] Failed to send immediate check-in: %v", checkinErr)
		} else {
			log.Printf("[Heartbeat] Immediate check-in sent successfully")
		}
	} else {
		log.Printf("[Heartbeat] Failed to get system metrics for immediate check-in: %v", err)
	}

	log.Printf("[Heartbeat] Rapid polling disabled successfully")
	return nil
}

// reportSystemInfo collects and reports detailed system information to the server
func reportSystemInfo(apiClient *client.Client, cfg *config.Config) error {
	// Collect detailed system information
	sysInfo, err := system.GetSystemInfo(version.Version)
	if err != nil {
		return fmt.Errorf("failed to get system info: %w", err)
	}

	// Create system info report
	report := client.SystemInfoReport{
		Timestamp:   time.Now(),
		CPUModel:    sysInfo.CPUInfo.ModelName,
		CPUCores:    sysInfo.CPUInfo.Cores,
		CPUThreads:  sysInfo.CPUInfo.Threads,
		MemoryTotal: sysInfo.MemoryInfo.Total,
		DiskTotal:   uint64(0),
		DiskUsed:    uint64(0),
		IPAddress:   sysInfo.IPAddress,
		Processes:   sysInfo.RunningProcesses,
		Uptime:      sysInfo.Uptime,
		Metadata:    make(map[string]interface{}),
	}

	// Add primary disk info
	if len(sysInfo.DiskInfo) > 0 {
		primaryDisk := sysInfo.DiskInfo[0]
		report.DiskTotal = primaryDisk.Total
		report.DiskUsed = primaryDisk.Used
		report.Metadata["disk_mount"] = primaryDisk.Mountpoint
		report.Metadata["disk_filesystem"] = primaryDisk.Filesystem
	}

	// Add collection timestamp and additional metadata
	report.Metadata["collected_at"] = time.Now().Format(time.RFC3339)
	report.Metadata["hostname"] = sysInfo.Hostname
	report.Metadata["os_type"] = sysInfo.OSType
	report.Metadata["os_version"] = sysInfo.OSVersion
	report.Metadata["os_architecture"] = sysInfo.OSArchitecture

	// Add any existing metadata from system info
	for key, value := range sysInfo.Metadata {
		report.Metadata[key] = value
	}

	// Report to server
	if err := apiClient.ReportSystemInfo(cfg.AgentID, report); err != nil {
		return fmt.Errorf("failed to report system info: %w", err)
	}

	return nil
}

// handleReboot handles reboot command
func handleReboot(apiClient *client.Client, cfg *config.Config, ackTracker *acknowledgment.Tracker, commandID string, params map[string]interface{}) error {
	log.Println("[Reboot] Processing reboot request...")

	// Parse parameters
	delayMinutes := 1 // Default to 1 minute
	message := "System reboot requested by RedFlag"

	if delay, ok := params["delay_minutes"]; ok {
		if delayFloat, ok := delay.(float64); ok {
			delayMinutes = int(delayFloat)
		}
	}
	if msg, ok := params["message"].(string); ok && msg != "" {
		message = msg
	}

	log.Printf("[Reboot] Scheduling system reboot in %d minute(s): %s", delayMinutes, message)

	var cmd *exec.Cmd

	// Execute platform-specific reboot command
	if runtime.GOOS == "linux" {
		// Linux: shutdown -r +MINUTES "message"
		cmd = exec.Command("shutdown", "-r", fmt.Sprintf("+%d", delayMinutes), message)
	} else if runtime.GOOS == "windows" {
		// Windows: shutdown /r /t SECONDS /c "message"
		delaySeconds := delayMinutes * 60
		cmd = exec.Command("shutdown", "/r", "/t", fmt.Sprintf("%d", delaySeconds), "/c", message)
	} else {
		err := fmt.Errorf("reboot not supported on platform: %s", runtime.GOOS)
		log.Printf("[Reboot] Error: %v", err)

		// Report failure
		logReport := client.LogReport{
			CommandID:       commandID,
			Action:          "reboot",
			Result:          "failed",
			Stdout:          "",
			Stderr:          err.Error(),
			ExitCode:        1,
			DurationSeconds: 0,
		}
		reportLogWithAck(apiClient, cfg, ackTracker, logReport)
		return err
	}

	// Execute reboot command
	output, err := cmd.CombinedOutput()
	if err != nil {
		log.Printf("[Reboot] Failed to schedule reboot: %v", err)
		log.Printf("[Reboot] Output: %s", string(output))

		// Report failure
		logReport := client.LogReport{
			CommandID:       commandID,
			Action:          "reboot",
			Result:          "failed",
			Stdout:          string(output),
			Stderr:          err.Error(),
			ExitCode:        1,
			DurationSeconds: 0,
		}
		reportLogWithAck(apiClient, cfg, ackTracker, logReport)
		return err
	}

	log.Printf("[Reboot] System reboot scheduled successfully")
	log.Printf("[Reboot] The system will reboot in %d minute(s)", delayMinutes)

	// Report success
	logReport := client.LogReport{
		CommandID:       commandID,
		Action:          "reboot",
		Result:          "success",
		Stdout:          fmt.Sprintf("System reboot scheduled for %d minute(s) from now. Message: %s", delayMinutes, message),
		Stderr:          "",
		ExitCode:        0,
		DurationSeconds: 0,
	}

	if reportErr := reportLogWithAck(apiClient, cfg, ackTracker, logReport); reportErr != nil {
		log.Printf("[Reboot] Failed to report reboot command result: %v", reportErr)
	}

	return nil
}

// formatTimeSince formats a duration as "X time ago"
func formatTimeSince(t time.Time) string {
	duration := time.Since(t)
	if duration < time.Minute {
		return fmt.Sprintf("%d seconds ago", int(duration.Seconds()))
	} else if duration < time.Hour {
		return fmt.Sprintf("%d minutes ago", int(duration.Minutes()))
	} else if duration < 24*time.Hour {
		return fmt.Sprintf("%d hours ago", int(duration.Hours()))
	} else {
		return fmt.Sprintf("%d days ago", int(duration.Hours()/24))
	}
}
