package handlers

import (
	"fmt"
	"log"
	"net/http"
	"strconv"
	"time"

	"github.com/Fimeg/RedFlag/aggregator-server/internal/database/queries"
	"github.com/Fimeg/RedFlag/aggregator-server/internal/models"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"github.com/jmoiron/sqlx"
)

// UnifiedUpdateHandler processes all update reports (metrics, package updates, etc.)
type UnifiedUpdateHandler struct {
	db               *sqlx.DB
	agentQueries     *queries.AgentQueries
	updateQueries    *queries.UpdateQueries
	subsystemQueries *queries.SubsystemQueries
	commandQueries   *queries.CommandQueries
	agentHandler     *AgentHandler
	logger           *log.Logger
}

// NewUnifiedUpdateHandler creates a new update handler
func NewUnifiedUpdateHandler(db *sqlx.DB, logger *log.Logger, ah *AgentHandler) *UnifiedUpdateHandler {
	return &UnifiedUpdateHandler{
		db:               db,
		agentQueries:     queries.NewAgentQueries(db),
		updateQueries:    queries.NewUpdateQueries(db),
		subsystemQueries: queries.NewSubsystemQueries(db),
		commandQueries:   queries.NewCommandQueries(db),
		agentHandler:     ah,
		logger:           logger,
	}
}

// Report handles POST /api/v1/agents/:id/updates
func (h *UnifiedUpdateHandler) Report(c *gin.Context) {
	agentIDStr := c.Param("id")
	agentID, err := uuid.Parse(agentIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid agent ID"})
		return
	}

	// Update last_seen timestamp
	if err := h.agentQueries.UpdateAgentLastSeen(agentID); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to update last seen"})
		return
	}

	var report models.UpdateReportRequest
	if err := c.ShouldBindJSON(&report); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// Validate report
	if err := h.validateReport(&report); err != nil {
		c.JSON(http.StatusUnprocessableEntity, gin.H{"error": err.Error()})
		return
	}

	// Route to appropriate handler based on report type
	if h.isPackageUpdateReport(&report) {
		if err := h.handlePackageUpdateReport(agentID, &report); err != nil {
			h.logger.Printf("Failed to handle package update report: %v", err)
			c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to process updates"})
			return
		}
	} else {
		c.JSON(http.StatusBadRequest, gin.H{"error": "unknown report type"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"status":     "received",
		"count":      len(report.Updates),
		"command_id": report.CommandID,
	})
}

// validateReport validates the update report
func (h *UnifiedUpdateHandler) validateReport(report *models.UpdateReportRequest) error {
	if report.Timestamp.IsZero() {
		return fmt.Errorf("timestamp is required")
	}

	// Validate updates
	if len(report.Updates) > 0 {
		for i, update := range report.Updates {
			if update.PackageName == "" {
				return fmt.Errorf("update[%d]: package name is required", i)
			}
			if update.PackageType == "" {
				return fmt.Errorf("update[%d]: package type is required", i)
			}
			if update.AvailableVersion == "" {
				return fmt.Errorf("update[%d]: available version is required", i)
			}
		}
	}

	return nil
}

// isPackageUpdateReport determines if the report contains package updates
func (h *UnifiedUpdateHandler) isPackageUpdateReport(report *models.UpdateReportRequest) bool {
	return len(report.Updates) > 0
}

// handlePackageUpdateReport processes package update data
func (h *UnifiedUpdateHandler) handlePackageUpdateReport(agentID uuid.UUID, report *models.UpdateReportRequest) error {
	// Convert update report items to events
	events := make([]models.UpdateEvent, 0, len(report.Updates))
	for _, item := range report.Updates {
		event := models.UpdateEvent{
			ID:               uuid.New(),
			AgentID:          agentID,
			PackageType:      item.PackageType,
			PackageName:      item.PackageName,
			VersionFrom:      item.CurrentVersion,
			VersionTo:        item.AvailableVersion,
			Severity:         item.Severity,
			RepositorySource: item.RepositorySource,
			Metadata:         item.Metadata,
			EventType:        "discovered",
			CreatedAt:        report.Timestamp,
		}
		events = append(events, event)
	}

	// Store events in batch
	if err := h.updateQueries.CreateUpdateEventsBatch(events); err != nil {
		return fmt.Errorf("failed to create update events: %w", err)
	}

	return nil
}

// ListUpdates retrieves updates with filtering
func (h *UnifiedUpdateHandler) ListUpdates(c *gin.Context) {
	filters := &models.UpdateFilters{
		Status:      c.Query("status"),
		Severity:    c.Query("severity"),
		PackageType: c.Query("package_type"),
	}

	if agentIDStr := c.Query("agent_id"); agentIDStr != "" {
		agentID, err := uuid.Parse(agentIDStr)
		if err == nil {
			filters.AgentID = agentID
		}
	}

	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "50"))
	filters.Page = page
	filters.PageSize = pageSize

	updates, total, err := h.updateQueries.ListUpdatesFromState(filters)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list updates"})
		return
	}

	stats, err := h.updateQueries.GetAllUpdateStats()
	if err != nil {
		stats = &models.UpdateStats{}
	}

	c.JSON(http.StatusOK, gin.H{
		"updates":   updates,
		"total":     total,
		"page":      page,
		"page_size": pageSize,
		"stats":     stats,
	})
}

// GetUpdate retrieves a single update by ID
func (h *UnifiedUpdateHandler) GetUpdate(c *gin.Context) {
	idStr := c.Param("id")
	id, err := uuid.Parse(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid update ID"})
		return
	}

	update, err := h.updateQueries.GetUpdateByID(id)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "update not found"})
		return
	}

	c.JSON(http.StatusOK, update)
}

// ApproveUpdate marks an update as approved
func (h *UnifiedUpdateHandler) ApproveUpdate(c *gin.Context) {
	idStr := c.Param("id")
	id, err := uuid.Parse(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid update ID"})
		return
	}

	if err := h.updateQueries.ApproveUpdate(id, "admin"); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("failed to approve update: %v", err)})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "update approved"})
}

// isValidResult checks if the result value complies with the database constraint
func isValidUpdateResult(result string) bool {
	validResults := map[string]bool{
		"success": true,
		"failed":  true,
		"partial": true,
	}
	return validResults[result]
}

// ReportLog handles update execution logs from agents
func (h *UnifiedUpdateHandler) ReportLog(c *gin.Context) {
	agentID := c.MustGet("agent_id").(uuid.UUID)

	if err := h.agentQueries.UpdateAgentLastSeen(agentID); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to update last seen"})
		return
	}

	var req models.UpdateLogRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	validResult := req.Result
	if !isValidUpdateResult(validResult) {
		if validResult == "timed_out" || validResult == "timeout" || validResult == "cancelled" {
			validResult = "failed"
		} else {
			validResult = "failed"
		}
	}

	logEntry := &models.UpdateLog{
		ID:              uuid.New(),
		AgentID:         agentID,
		Action:          req.Action,
		Result:          validResult,
		Stdout:          req.Stdout,
		Stderr:          req.Stderr,
		ExitCode:        req.ExitCode,
		DurationSeconds: req.DurationSeconds,
		ExecutedAt:      time.Now(),
	}

	if err := h.updateQueries.CreateUpdateLog(logEntry); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to save log"})
		return
	}

	// Update command status if command_id is provided
	if req.CommandID != "" {
		commandID, err := uuid.Parse(req.CommandID)
		if err != nil {
			log.Printf("Warning: Invalid command ID format in log request: %s\n", req.CommandID)
		} else {
			result := models.JSONB{
				"stdout":           req.Stdout,
				"stderr":           req.Stderr,
				"exit_code":        req.ExitCode,
				"duration_seconds": req.DurationSeconds,
				"logged_at":        time.Now(),
			}
			log.Printf("DEBUG: ReportLog - Marking command %s as completed for agent %s", commandID, agentID)


			if req.Result == "success" || req.Result == "completed" {
				if err := h.commandQueries.MarkCommandCompleted(commandID, result); err != nil {
					log.Printf("Warning: Failed to mark command %s as completed: %v\n", commandID, err)
				}

				command, err := h.commandQueries.GetCommandByID(commandID)
				if err == nil && command.CommandType == models.CommandTypeConfirmDependencies {
					if packageName, ok := command.Params["package_name"].(string); ok {
						if packageType, ok := command.Params["package_type"].(string); ok {
							var completionTime *time.Time
							if loggedAtStr, ok := command.Result["logged_at"].(string); ok {
								if parsed, err := time.Parse(time.RFC3339Nano, loggedAtStr); err == nil {
									completionTime = &parsed
								}
							}

							if err := h.updateQueries.UpdatePackageStatus(agentID, packageType, packageName, "updated", nil, completionTime); err != nil {
								log.Printf("Warning: Failed to update package status for %s/%s: %v", packageType, packageName, err)
							} else {
								log.Printf("[INFO] [server] [updates] package_updated package=%s type=%s", packageName, packageType)
							}
						}
					}
				}
			} else if req.Result == "failed" || req.Result == "dry_run_failed" {
				if err := h.commandQueries.MarkCommandFailed(commandID, result); err != nil {
					log.Printf("Warning: Failed to mark command %s as failed: %v\n", commandID, err)
				}
			} else {
				if err := h.commandQueries.UpdateCommandResult(commandID, result); err != nil {
					log.Printf("Warning: Failed to update command %s result: %v\n", commandID, err)
				}
			}
		}
	}

	c.JSON(http.StatusOK, gin.H{"message": "log recorded"})
}

// GetPackageHistory returns version history for a specific package
func (h *UnifiedUpdateHandler) GetPackageHistory(c *gin.Context) {
	agentIDStr := c.Param("agent_id")
	agentID, err := uuid.Parse(agentIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid agent ID"})
		return
	}

	packageType := c.Query("package_type")
	packageName := c.Query("package_name")

	if packageType == "" || packageName == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "package_type and package_name are required"})
		return
	}

	limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))

	history, err := h.updateQueries.GetPackageHistory(agentID, packageType, packageName, limit)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get package history"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"history":      history,
		"package_type": packageType,
		"package_name": packageName,
		"count":        len(history),
	})
}

// UpdatePackageStatus updates the status of a package
func (h *UnifiedUpdateHandler) UpdatePackageStatus(c *gin.Context) {
	agentIDStr := c.Param("agent_id")
	agentID, err := uuid.Parse(agentIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid agent ID"})
		return
	}

	var req struct {
		PackageType string                 `json:"package_type" binding:"required"`
		PackageName string                 `json:"package_name" binding:"required"`
		Status      string                 `json:"status" binding:"required"`
		Metadata    map[string]interface{} `json:"metadata"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	if err := h.updateQueries.UpdatePackageStatus(agentID, req.PackageType, req.PackageName, req.Status, req.Metadata, nil); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to update package status"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "package status updated"})
}

// shouldEnableHeartbeat checks if heartbeat is already active for an agent
func (h *UnifiedUpdateHandler) shouldEnableHeartbeat(agentID uuid.UUID, durationMinutes int) (bool, error) {
	agent, err := h.agentQueries.GetAgentByID(agentID)
	if err != nil {
		log.Printf("Warning: Failed to get agent %s for heartbeat check: %v", agentID, err)
		return true, nil
	}

	if enabled, ok := agent.Metadata["rapid_polling_enabled"].(bool); ok && enabled {
		if untilStr, ok := agent.Metadata["rapid_polling_until"].(string); ok {
			until, err := time.Parse(time.RFC3339, untilStr)
			if err == nil && until.After(time.Now().Add(5*time.Minute)) {
				log.Printf("[Heartbeat] Agent %s already has active heartbeat until %s (skipping)", agentID, untilStr)
				return false, nil
			}
		}
	}

	return true, nil
}

// InstallUpdate marks an update as ready for installation
func (h *UnifiedUpdateHandler) InstallUpdate(c *gin.Context) {
	idStr := c.Param("id")
	id, err := uuid.Parse(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid update ID"})
		return
	}

	update, err := h.updateQueries.GetUpdateByID(id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get update details"})
		return
	}

	command := &models.AgentCommand{
		ID:          uuid.New(),
		AgentID:     update.AgentID,
		CommandType: models.CommandTypeDryRunUpdate,
		Params: map[string]interface{}{
			"update_id":    id.String(),
			"package_name": update.PackageName,
			"package_type": update.PackageType,
		},
		Status:    models.CommandStatusPending,
		Source:    models.CommandSourceManual,
		CreatedAt: time.Now(),
	}

	if shouldEnable, err := h.shouldEnableHeartbeat(update.AgentID, 10); err == nil && shouldEnable {
		heartbeatCmd := &models.AgentCommand{
			ID:          uuid.New(),
			AgentID:     update.AgentID,
			CommandType: models.CommandTypeEnableHeartbeat,
			Params: models.JSONB{
				"duration_minutes": 10,
			},
			Status:    models.CommandStatusPending,
			Source:    models.CommandSourceSystem,
			CreatedAt: time.Now(),
		}

		if err := h.agentHandler.signAndCreateCommand(heartbeatCmd); err != nil {
			log.Printf("[Heartbeat] Warning: Failed to create heartbeat command for agent %s: %v", update.AgentID, err)
		}
	}

	if err := h.agentHandler.signAndCreateCommand(command); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create dry run command"})
		return
	}

	if err := h.updateQueries.SetCheckingDependencies(id); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to update package status"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"message":    "dry run command created for agent",
		"command_id": command.ID.String(),
	})
}

// ReportDependencies handles dependency reporting from agents after dry run
func (h *UnifiedUpdateHandler) ReportDependencies(c *gin.Context) {
	agentID := c.MustGet("agent_id").(uuid.UUID)

	if err := h.agentQueries.UpdateAgentLastSeen(agentID); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to update last seen"})
		return
	}

	var req models.DependencyReportRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// Auto-approve if no dependencies
	if len(req.Dependencies) == 0 {
		update, err := h.updateQueries.GetUpdateByPackage(agentID, req.PackageType, req.PackageName)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get update details"})
			return
		}

		command := &models.AgentCommand{
			ID:          uuid.New(),
			AgentID:     agentID,
			CommandType: models.CommandTypeConfirmDependencies,
			Params: map[string]interface{}{
				"update_id":     update.ID.String(),
				"package_name":  req.PackageName,
				"package_type":  req.PackageType,
				"dependencies":  []string{},
			},
			Status:    models.CommandStatusPending,
			Source:    models.CommandSourceManual,
			CreatedAt: time.Now(),
		}

		if shouldEnable, err := h.shouldEnableHeartbeat(agentID, 10); err == nil && shouldEnable {
			heartbeatCmd := &models.AgentCommand{
				ID:          uuid.New(),
				AgentID:     agentID,
				CommandType: models.CommandTypeEnableHeartbeat,
				Params: models.JSONB{
					"duration_minutes": 10,
				},
				Status:    models.CommandStatusPending,
				Source:    models.CommandSourceSystem,
				CreatedAt: time.Now(),
			}

			if err := h.agentHandler.signAndCreateCommand(heartbeatCmd); err != nil {
				log.Printf("[Heartbeat] Warning: Failed to create heartbeat command for agent %s: %v", agentID, err)
			}
		}

		if err := h.agentHandler.signAndCreateCommand(command); err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create installation command"})
			return
		}

		if err := h.updateQueries.SetInstallingWithNoDependencies(update.ID, req.Dependencies); err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to update package status to installing"})
			return
		}

		c.JSON(http.StatusOK, gin.H{
			"message":    "no dependencies found - installation command created automatically",
			"command_id": command.ID.String(),
		})
		return
	}

	// Require manual approval for dependencies
	if err := h.updateQueries.SetPendingDependencies(agentID, req.PackageType, req.PackageName, req.Dependencies); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to update package status"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "dependencies reported and status updated"})
}

// ConfirmDependencies handles user confirmation to proceed with dependency installation
func (h *UnifiedUpdateHandler) ConfirmDependencies(c *gin.Context) {
	idStr := c.Param("id")
	id, err := uuid.Parse(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid update ID"})
		return
	}

	update, err := h.updateQueries.GetUpdateByID(id)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "update not found"})
		return
	}

	command := &models.AgentCommand{
		ID:          uuid.New(),
		AgentID:     update.AgentID,
		CommandType: models.CommandTypeConfirmDependencies,
		Params: map[string]interface{}{
			"update_id":    id.String(),
			"package_name": update.PackageName,
			"package_type": update.PackageType,
			"dependencies": update.Metadata["dependencies"],
		},
		Status:    models.CommandStatusPending,
		Source:    models.CommandSourceManual,
		CreatedAt: time.Now(),
	}

	if shouldEnable, err := h.shouldEnableHeartbeat(update.AgentID, 10); err == nil && shouldEnable {
		heartbeatCmd := &models.AgentCommand{
			ID:          uuid.New(),
			AgentID:     update.AgentID,
			CommandType: models.CommandTypeEnableHeartbeat,
			Params: models.JSONB{
				"duration_minutes": 10,
			},
			Status:    models.CommandStatusPending,
			Source:    models.CommandSourceSystem,
			CreatedAt: time.Now(),
		}

		if err := h.agentHandler.signAndCreateCommand(heartbeatCmd); err != nil {
			log.Printf("[Heartbeat] Warning: Failed to create heartbeat command for agent %s: %v", update.AgentID, err)
		}
	}

	if err := h.agentHandler.signAndCreateCommand(command); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create confirmation command"})
		return
	}

	if err := h.updateQueries.InstallUpdate(id); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to update package status"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"message":    "dependency installation confirmed and command created",
		"command_id": command.ID.String(),
	})
}

// ApproveUpdates handles bulk approval of updates
func (h *UnifiedUpdateHandler) ApproveUpdates(c *gin.Context) {
	var req struct {
		UpdateIDs   []string `json:"update_ids" binding:"required"`
		ScheduledAt *string  `json:"scheduled_at"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	updateIDs := make([]uuid.UUID, 0, len(req.UpdateIDs))
	for _, idStr := range req.UpdateIDs {
		id, err := uuid.Parse(idStr)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "invalid update ID: " + idStr})
			return
		}
		updateIDs = append(updateIDs, id)
	}

	if err := h.updateQueries.BulkApproveUpdates(updateIDs, "admin"); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to approve updates"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"message": "updates approved",
		"count":   len(updateIDs),
	})
}

// RejectUpdate rejects a single update
func (h *UnifiedUpdateHandler) RejectUpdate(c *gin.Context) {
	idStr := c.Param("id")
	id, err := uuid.Parse(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid update ID"})
		return
	}

	if err := h.updateQueries.RejectUpdate(id, "admin"); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to reject update"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "update rejected"})
}

// GetAllLogs retrieves logs across all agents with filtering
func (h *UnifiedUpdateHandler) GetAllLogs(c *gin.Context) {
	filters := &models.LogFilters{
		Action: c.Query("action"),
		Result: c.Query("result"),
	}

	if agentIDStr := c.Query("agent_id"); agentIDStr != "" {
		agentID, err := uuid.Parse(agentIDStr)
		if err == nil {
			filters.AgentID = agentID
		}
	}

	if sinceStr := c.Query("since"); sinceStr != "" {
		sinceTime, err := time.Parse(time.RFC3339, sinceStr)
		if err == nil {
			filters.Since = &sinceTime
		}
	}

	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "100"))
	filters.Page = page
	filters.PageSize = pageSize

	items, total, err := h.updateQueries.GetAllUnifiedHistory(filters)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to retrieve history"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"logs":      items,
		"total":     total,
		"page":      page,
		"page_size": pageSize,
	})
}

// GetUpdateLogs retrieves installation logs for a specific update
func (h *UnifiedUpdateHandler) GetUpdateLogs(c *gin.Context) {
	idStr := c.Param("id")
	id, err := uuid.Parse(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid update ID"})
		return
	}

	limit, _ := strconv.Atoi(c.DefaultQuery("limit", "50"))

	logs, err := h.updateQueries.GetUpdateLogs(id, limit)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to retrieve update logs"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"logs":  logs,
		"count": len(logs),
	})
}

// RetryCommand retries a failed command
func (h *UnifiedUpdateHandler) RetryCommand(c *gin.Context) {
	idStr := c.Param("id")
	id, err := uuid.Parse(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid command ID"})
		return
	}

	// Get the original command
	original, err := h.commandQueries.GetCommandByID(id)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("failed to get original command: %v", err)})
		return
	}

	// Only allow retry of failed, timed_out, or cancelled commands
	if original.Status != "failed" && original.Status != "timed_out" && original.Status != "cancelled" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "command must be failed, timed_out, or cancelled to retry"})
		return
	}

	// Create new command with same parameters, linking it to the original
	newCommand := &models.AgentCommand{
		ID:            uuid.New(),
		AgentID:       original.AgentID,
		CommandType:   original.CommandType,
		Params:        original.Params,
		Status:        models.CommandStatusPending,
		CreatedAt:     time.Now(),
		RetriedFromID: &id,
	}

	// Sign and store the new command
	if err := h.agentHandler.signAndCreateCommand(newCommand); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("failed to retry command: %v", err)})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"message":    "command retry created",
		"command_id": newCommand.ID.String(),
		"new_id":     newCommand.ID.String(),
	})
}

// CancelCommand cancels a pending command
func (h *UnifiedUpdateHandler) CancelCommand(c *gin.Context) {
	idStr := c.Param("id")
	id, err := uuid.Parse(idStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid command ID"})
		return
	}

	if err := h.commandQueries.CancelCommand(id); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("failed to cancel command: %v", err)})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "command cancelled"})
}

// GetActiveCommands retrieves currently active commands
func (h *UnifiedUpdateHandler) GetActiveCommands(c *gin.Context) {
	commands, err := h.commandQueries.GetActiveCommands()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to retrieve active commands"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"commands": commands,
		"count":    len(commands),
	})
}

// GetRecentCommands retrieves recent commands
func (h *UnifiedUpdateHandler) GetRecentCommands(c *gin.Context) {
	limit, _ := strconv.Atoi(c.DefaultQuery("limit", "50"))

	commands, err := h.commandQueries.GetRecentCommands(limit)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to retrieve recent commands"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"commands": commands,
		"count":    len(commands),
		"limit":    limit,
	})
}

// ClearFailedCommands removes failed commands
func (h *UnifiedUpdateHandler) ClearFailedCommands(c *gin.Context) {
	olderThanDaysStr := c.Query("older_than_days")
	onlyRetriedStr := c.Query("only_retried")
	allFailedStr := c.Query("all_failed")

	var count int64
	var err error

	olderThanDays := 7
	if olderThanDaysStr != "" {
		if days, err := strconv.Atoi(olderThanDaysStr); err == nil && days > 0 {
			olderThanDays = days
		}
	}

	onlyRetried := onlyRetriedStr == "true"
	allFailed := allFailedStr == "true"

	if allFailed {
		count, err = h.commandQueries.ClearAllFailedCommandsRegardlessOfAge()
	} else if onlyRetried {
		count, err = h.commandQueries.ClearRetriedFailedCommands(olderThanDays)
	} else {
		count, err = h.commandQueries.ClearOldFailedCommands(olderThanDays)
	}

	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"error":   "failed to clear failed commands",
			"details": err.Error(),
		})
		return
	}

	message := fmt.Sprintf("Archived %d failed commands", count)
	if count > 0 {
		message += ". WARNING: This shouldn't be necessary if the retry logic is working properly"
		message += " (History preserved - commands moved to archived status)"
	}

	c.JSON(http.StatusOK, gin.H{
		"message": message,
		"count":   count,
	})
}

// GetBatchStatus returns recent batch processing status for an agent
func (h *UnifiedUpdateHandler) GetBatchStatus(c *gin.Context) {
	agentIDStr := c.Param("agent_id")
	agentID, err := uuid.Parse(agentIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid agent ID"})
		return
	}

	limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))

	batches, err := h.updateQueries.GetBatchStatus(agentID, limit)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get batch status"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"batches": batches,
		"count":   len(batches),
	})
}

// GetActiveOperations retrieves currently running operations
func (h *UnifiedUpdateHandler) GetActiveOperations(c *gin.Context) {
	operations, err := h.updateQueries.GetActiveOperations()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to retrieve active operations"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"operations": operations,
		"count":      len(operations),
	})
}
