package handlers

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

	"github.com/gin-gonic/gin"
	"github.com/starfleetcptn/gomft/components"
	"github.com/starfleetcptn/gomft/internal/db"
)

// HandleJobs handles the GET /jobs route
func (h *Handlers) HandleJobs(c *gin.Context) {
	userID := c.GetUint("userID")

	var jobs []db.Job
	h.DB.Where("created_by = ?", userID).Preload("Config").Find(&jobs)

	// Create a map to store config counts for each job
	configCount := make(map[uint]int)

	// Count configurations for each job
	for _, job := range jobs {
		// Get all configurations for this job
		configs, err := h.DB.GetConfigsForJob(job.ID)
		if err != nil {
			c.Error(fmt.Errorf("error loading configurations for job %d: %v", job.ID, err))
			configCount[job.ID] = 0
		} else {
			configCount[job.ID] = len(configs)
		}
	}

	data := components.JobsData{
		Jobs:        jobs,
		ConfigCount: configCount,
	}
	components.Jobs(c, data).Render(c, c.Writer)
}

// HandleJobRunDetails handles the GET /job/:id route
func (h *Handlers) HandleJobRunDetails(c *gin.Context) {
	userID := c.GetUint("userID")
	jobID := c.Param("id")

	// Get job history
	var jobHistory db.JobHistory
	if err := h.DB.First(&jobHistory, jobID).Error; err != nil {
		c.String(http.StatusNotFound, "Job not found")
		return
	}

	// Get job
	var job db.Job
	if err := h.DB.First(&job, jobHistory.JobID).Error; err != nil {
		c.String(http.StatusNotFound, "Job not found")
		return
	}

	// Verify that the user owns this job
	if job.CreatedBy != userID {
		c.String(http.StatusForbidden, "You don't have permission to view this job run")
		return
	}

	// Get the config
	var config db.TransferConfig

	// First try to get the specific config used in this job history record
	configID := jobHistory.ConfigID

	// If no ConfigID is set in the history, fall back to the job's primary ConfigID
	if configID == 0 {
		configID = job.ConfigID
	}

	if err := h.DB.First(&config, configID).Error; err != nil {
		c.String(http.StatusNotFound, "Configuration not found")
		return
	}

	data := components.JobRunDetailsData{
		JobHistory: jobHistory,
		Job:        job,
		Config:     config,
	}

	components.JobRunDetails(c.Request.Context(), data).Render(c, c.Writer)
}

// HandleNewJob handles the GET /jobs/new route
func (h *Handlers) HandleNewJob(c *gin.Context) {
	// Get available configs for the user
	userID := c.GetUint("userID")
	var configs []db.TransferConfig
	h.DB.Where("created_by = ?", userID).Find(&configs)

	data := components.JobFormData{
		Job:     &db.Job{},
		Configs: configs,
		IsNew:   true,
	}
	components.JobForm(c.Request.Context(), data).Render(c, c.Writer)
}

// HandleEditJob handles the GET /jobs/:id/edit route
func (h *Handlers) HandleEditJob(c *gin.Context) {
	id := c.Param("id")
	userID := c.GetUint("userID")

	var job db.Job
	if err := h.DB.First(&job, id).Error; err != nil {
		c.Redirect(http.StatusFound, "/jobs")
		return
	}

	// Check if user owns this job
	if job.CreatedBy != userID {
		// Check if user is admin
		isAdmin, exists := c.Get("isAdmin")
		if !exists || isAdmin != true {
			c.Redirect(http.StatusFound, "/jobs")
			return
		}
	}

	// Get available configs for the user
	var configs []db.TransferConfig
	h.DB.Where("created_by = ?", userID).Find(&configs)

	data := components.JobFormData{
		Job:     &job,
		Configs: configs,
		IsNew:   false,
	}
	components.JobForm(c.Request.Context(), data).Render(c, c.Writer)
}

// HandleCreateJob handles the POST /jobs route
func (h *Handlers) HandleCreateJob(c *gin.Context) {
	userID := c.GetUint("userID")

	// Debug logging
	log.Printf("HandleCreateJob: Form data received: %v", c.Request.PostForm)

	// Parse form data
	var job db.Job
	if err := c.ShouldBind(&job); err != nil {
		c.String(http.StatusBadRequest, "Invalid form data")
		return
	}

	// Debug logging
	log.Printf("HandleCreateJob: Job after binding: %+v", job)

	// Get multiple config IDs from form
	configIDs := c.PostFormArray("config_ids[]")
	if len(configIDs) == 0 {
		c.String(http.StatusBadRequest, "At least one configuration must be selected")
		return
	}

	// Debug logging
	log.Printf("HandleCreateJob: config_ids[]: %v", configIDs)

	// Process config IDs
	var configIDsList []uint

	// Check if we have an explicit order specified
	configOrder := c.PostForm("config_order")
	log.Printf("HandleCreateJob: config_order: %s", configOrder)

	if configOrder != "" {
		// Parse the ordered list
		orderStrings := strings.Split(configOrder, ",")
		log.Printf("HandleCreateJob: order strings: %v", orderStrings)

		for _, configIDStr := range orderStrings {
			configID, err := strconv.ParseUint(configIDStr, 10, 32)
			if err != nil {
				log.Printf("HandleCreateJob: Error parsing config ID: %v", err)
				c.String(http.StatusBadRequest, "Invalid configuration ID format in order")
				return
			}

			// Verify that the config exists and belongs to the user
			var config db.TransferConfig
			if err := h.DB.First(&config, configID).Error; err != nil {
				log.Printf("HandleCreateJob: Invalid config ID: %d, error: %v", configID, err)
				c.String(http.StatusBadRequest, "Invalid configuration selected")
				return
			}

			// Check if the config belongs to the user
			if config.CreatedBy != userID {
				// Check if user is admin
				isAdmin, exists := c.Get("isAdmin")
				if !exists || isAdmin != true {
					c.String(http.StatusForbidden, "You do not have permission to use this configuration")
					return
				}
			}

			configIDsList = append(configIDsList, uint(configID))
		}
	} else {
		// Fall back to unordered config IDs
		log.Printf("HandleCreateJob: No config_order found, using checkbox order")
		for _, configIDStr := range configIDs {
			configID, err := strconv.ParseUint(configIDStr, 10, 32)
			if err != nil {
				c.String(http.StatusBadRequest, "Invalid configuration ID format")
				return
			}

			// Verify that the config exists and belongs to the user
			var config db.TransferConfig
			if err := h.DB.First(&config, configID).Error; err != nil {
				c.String(http.StatusBadRequest, "Invalid configuration selected")
				return
			}

			// Check if the config belongs to the user
			if config.CreatedBy != userID {
				// Check if user is admin
				isAdmin, exists := c.Get("isAdmin")
				if !exists || isAdmin != true {
					c.String(http.StatusForbidden, "You do not have permission to use this configuration")
					return
				}
			}

			configIDsList = append(configIDsList, uint(configID))
		}
	}

	// Debug logging
	log.Printf("HandleCreateJob: Final configIDsList: %v", configIDsList)

	// Set the first config ID for backward compatibility
	if len(configIDsList) > 0 {
		job.ConfigID = configIDsList[0]

		// Verify that the config exists and belongs to the user (using the first config as primary)
		var config db.TransferConfig
		if err := h.DB.First(&config, job.ConfigID).Error; err != nil {
			c.String(http.StatusBadRequest, "Invalid configuration selected")
			return
		}

		// Check if the config belongs to the user
		if config.CreatedBy != userID {
			// Check if user is admin
			isAdmin, exists := c.Get("isAdmin")
			if !exists || isAdmin != true {
				c.String(http.StatusForbidden, "You do not have permission to use this configuration")
				return
			}
		}

		// If job name is empty, use the primary config name
		if job.Name == "" {
			job.Name = config.Name
		}
	}

	// Set the config IDs list
	job.SetConfigIDsList(configIDsList)

	// Debug logging
	log.Printf("HandleCreateJob: Job after setting ConfigIDsList: %+v", job)
	log.Printf("HandleCreateJob: Job.ConfigIDs: %s", job.ConfigIDs)

	// Set the boolean fields - handle both "on" and "true" values for checkboxes
	enabledVal := c.Request.FormValue("enabled")
	jobEnabledValue := enabledVal == "on" || enabledVal == "true"
	job.SetEnabled(jobEnabledValue)

	webhookEnabledVal := c.Request.FormValue("webhook_enabled")
	webhookEnabledValue := webhookEnabledVal == "on" || webhookEnabledVal == "true"
	job.SetWebhookEnabled(webhookEnabledValue)

	notifySuccessVal := c.Request.FormValue("notify_on_success")
	notifyOnSuccessValue := notifySuccessVal == "on" || notifySuccessVal == "true"
	job.SetNotifyOnSuccess(notifyOnSuccessValue)

	notifyFailureVal := c.Request.FormValue("notify_on_failure")
	notifyOnFailureValue := notifyFailureVal == "on" || notifyFailureVal == "true"
	job.SetNotifyOnFailure(notifyOnFailureValue)

	// Set created by user
	job.CreatedBy = userID

	// Clear the Config field to prevent GORM from creating a new config
	job.Config = db.TransferConfig{}

	// Start a transaction
	tx := h.DB.Begin()
	if tx.Error != nil {
		log.Printf("HandleCreateJob: Failed to begin transaction: %v", tx.Error)
		c.String(http.StatusInternalServerError, "Failed to begin transaction")
		return
	}

	// Create the job
	if err := tx.Create(&job).Error; err != nil {
		tx.Rollback()
		log.Printf("HandleCreateJob: Error creating job: %v", err)
		c.String(http.StatusInternalServerError, "Failed to create job")
		return
	}

	// Create audit log entry
	auditDetails := map[string]interface{}{
		"name":              job.Name,
		"schedule":          job.Schedule,
		"enabled":           job.GetEnabled(),
		"config_ids":        configIDsList,
		"webhook_enabled":   job.GetWebhookEnabled(),
		"notify_on_success": job.GetNotifyOnSuccess(),
		"notify_on_failure": job.GetNotifyOnFailure(),
	}

	auditLog := db.AuditLog{
		Action:     "create",
		EntityType: "job",
		EntityID:   job.ID,
		UserID:     userID,
		Details:    auditDetails,
		Timestamp:  time.Now(),
	}

	if err := tx.Create(&auditLog).Error; err != nil {
		tx.Rollback()
		log.Printf("HandleCreateJob: Error creating audit log: %v", err)
		c.String(http.StatusInternalServerError, "Failed to create audit log")
		return
	}

	// Commit the transaction
	if err := tx.Commit().Error; err != nil {
		log.Printf("HandleCreateJob: Error committing transaction: %v", err)
		c.String(http.StatusInternalServerError, "Failed to commit transaction")
		return
	}

	log.Printf("HandleCreateJob: Job successfully created with ID: %d", job.ID)

	// Schedule the job with the scheduler
	if err := h.Scheduler.ScheduleJob(&job); err != nil {
		c.String(http.StatusInternalServerError, "Job created but scheduling failed: "+err.Error())
		return
	}

	c.Redirect(http.StatusFound, "/jobs")
}

// HandleUpdateJob handles the PUT /jobs/:id route
func (h *Handlers) HandleUpdateJob(c *gin.Context) {
	id := c.Param("id")
	userID := c.GetUint("userID")

	// Debug logging
	log.Printf("HandleUpdateJob: Updating job ID: %s", id)
	log.Printf("HandleUpdateJob: Form data received: %v", c.Request.PostForm)

	var job db.Job
	if err := h.DB.First(&job, id).Error; err != nil {
		log.Printf("HandleUpdateJob: Job not found: %v", err)
		c.String(http.StatusNotFound, "Job not found")
		return
	}

	// Check if user owns this job
	if job.CreatedBy != userID {
		// Check if user is admin
		isAdmin, exists := c.Get("isAdmin")
		if !exists || isAdmin != true {
			c.String(http.StatusForbidden, "You do not have permission to update this job")
			return
		}
	}

	// Get the old job values for comparison
	oldJob := job
	log.Printf("HandleUpdateJob: Original job: %+v", oldJob)
	log.Printf("HandleUpdateJob: Original job ConfigIDs: %s", oldJob.ConfigIDs)

	// Parse form data
	if err := c.ShouldBind(&job); err != nil {
		log.Printf("HandleUpdateJob: Error binding form data: %v", err)
		c.String(http.StatusBadRequest, "Invalid form data")
		return
	}

	log.Printf("HandleUpdateJob: Job after binding: %+v", job)

	// Get multiple config IDs from form
	configIDs := c.PostFormArray("config_ids[]")
	if len(configIDs) == 0 {
		log.Printf("HandleUpdateJob: No config_ids[] found in form data")
		c.String(http.StatusBadRequest, "At least one configuration must be selected")
		return
	}

	log.Printf("HandleUpdateJob: config_ids[]: %v", configIDs)

	// Process config IDs
	var configIDsList []uint

	// Check if we have an explicit order specified
	configOrder := c.PostForm("config_order")
	log.Printf("HandleUpdateJob: config_order: %s", configOrder)

	if configOrder != "" {
		// Parse the ordered list
		orderStrings := strings.Split(configOrder, ",")
		log.Printf("HandleUpdateJob: order strings: %v", orderStrings)

		for _, configIDStr := range orderStrings {
			configID, err := strconv.ParseUint(configIDStr, 10, 32)
			if err != nil {
				log.Printf("HandleUpdateJob: Error parsing config ID: %v", err)
				c.String(http.StatusBadRequest, "Invalid configuration ID format in order")
				return
			}

			// Verify that the config exists
			var config db.TransferConfig
			if err := h.DB.First(&config, configID).Error; err != nil {
				log.Printf("HandleUpdateJob: Invalid config ID: %d, error: %v", configID, err)
				c.String(http.StatusBadRequest, "Invalid configuration selected")
				return
			}

			// Check if the config belongs to the user
			if config.CreatedBy != userID {
				// Check if user is admin
				isAdmin, exists := c.Get("isAdmin")
				if !exists || isAdmin != true {
					c.String(http.StatusForbidden, "You do not have permission to use this configuration")
					return
				}
			}

			configIDsList = append(configIDsList, uint(configID))
		}
	} else {
		// Fall back to unordered config IDs
		log.Printf("HandleUpdateJob: No config_order found, using checkbox order")
		for _, configIDStr := range configIDs {
			configID, err := strconv.ParseUint(configIDStr, 10, 32)
			if err != nil {
				c.String(http.StatusBadRequest, "Invalid configuration ID format")
				return
			}

			// Verify that the config exists
			var config db.TransferConfig
			if err := h.DB.First(&config, configID).Error; err != nil {
				c.String(http.StatusBadRequest, "Invalid configuration selected")
				return
			}

			// Check if the config belongs to the user
			if config.CreatedBy != userID {
				// Check if user is admin
				isAdmin, exists := c.Get("isAdmin")
				if !exists || isAdmin != true {
					c.String(http.StatusForbidden, "You do not have permission to use this configuration")
					return
				}
			}

			configIDsList = append(configIDsList, uint(configID))
		}
	}

	// Debug logging
	log.Printf("HandleUpdateJob: Final configIDsList: %v", configIDsList)

	// Set the first config ID for backward compatibility
	if len(configIDsList) > 0 {
		job.ConfigID = configIDsList[0]

		// If job name is empty, use the primary config name
		var config db.TransferConfig
		if err := h.DB.First(&config, job.ConfigID).Error; err == nil && job.Name == "" {
			job.Name = config.Name
		}
	}

	// Set the config IDs list
	job.SetConfigIDsList(configIDsList)

	// Debug logging
	log.Printf("HandleUpdateJob: Job after setting ConfigIDsList: %+v", job)
	log.Printf("HandleUpdateJob: Job.ConfigIDs: %s", job.ConfigIDs)

	// Set the boolean fields - handle both "on" and "true" values for checkboxes
	enabledVal := c.Request.FormValue("enabled")
	jobEnabledValue := enabledVal == "on" || enabledVal == "true"
	job.SetEnabled(jobEnabledValue)

	webhookEnabledVal := c.Request.FormValue("webhook_enabled")
	webhookEnabledValue := webhookEnabledVal == "on" || webhookEnabledVal == "true"
	job.SetWebhookEnabled(webhookEnabledValue)

	notifySuccessVal := c.Request.FormValue("notify_on_success")
	notifyOnSuccessValue := notifySuccessVal == "on" || notifySuccessVal == "true"
	job.SetNotifyOnSuccess(notifyOnSuccessValue)

	notifyFailureVal := c.Request.FormValue("notify_on_failure")
	notifyOnFailureValue := notifyFailureVal == "on" || notifyFailureVal == "true"
	job.SetNotifyOnFailure(notifyOnFailureValue)

	// Preserve fields that shouldn't be updated
	job.CreatedBy = oldJob.CreatedBy
	job.ID = oldJob.ID

	// Clear the Config field to prevent GORM from updating or creating a new config
	job.Config = db.TransferConfig{}

	// Start a transaction
	tx := h.DB.Begin()
	if tx.Error != nil {
		log.Printf("HandleUpdateJob: Failed to begin transaction: %v", tx.Error)
		c.String(http.StatusInternalServerError, "Failed to begin transaction")
		return
	}

	if err := tx.Save(&job).Error; err != nil {
		tx.Rollback()
		log.Printf("HandleUpdateJob: Error updating job: %v", err)
		c.String(http.StatusInternalServerError, "Failed to update job")
		return
	}

	// Create audit log entry
	auditDetails := map[string]interface{}{
		"name":              job.Name,
		"schedule":          job.Schedule,
		"enabled":           job.GetEnabled(),
		"config_ids":        configIDsList,
		"webhook_enabled":   job.GetWebhookEnabled(),
		"notify_on_success": job.GetNotifyOnSuccess(),
		"notify_on_failure": job.GetNotifyOnFailure(),
		"previous_state": map[string]interface{}{
			"name":              oldJob.Name,
			"schedule":          oldJob.Schedule,
			"enabled":           oldJob.GetEnabled(),
			"config_ids":        oldJob.GetConfigIDsList(),
			"webhook_enabled":   oldJob.GetWebhookEnabled(),
			"notify_on_success": oldJob.GetNotifyOnSuccess(),
			"notify_on_failure": oldJob.GetNotifyOnFailure(),
		},
	}

	auditLog := db.AuditLog{
		Action:     "update",
		EntityType: "job",
		EntityID:   job.ID,
		UserID:     userID,
		Details:    auditDetails,
		Timestamp:  time.Now(),
	}

	if err := tx.Create(&auditLog).Error; err != nil {
		tx.Rollback()
		log.Printf("HandleUpdateJob: Error creating audit log: %v", err)
		c.String(http.StatusInternalServerError, "Failed to create audit log")
		return
	}

	// Commit the transaction
	if err := tx.Commit().Error; err != nil {
		log.Printf("HandleUpdateJob: Error committing transaction: %v", err)
		c.String(http.StatusInternalServerError, "Failed to commit transaction")
		return
	}

	log.Printf("HandleUpdateJob: Job successfully updated")

	// Reschedule the job with the scheduler
	if err := h.Scheduler.ScheduleJob(&job); err != nil {
		c.String(http.StatusInternalServerError, "Job updated but scheduling failed: "+err.Error())
		return
	}

	c.Redirect(http.StatusFound, "/jobs")
}

// HandleDeleteJob handles the DELETE /jobs/:id route
func (h *Handlers) HandleDeleteJob(c *gin.Context) {
	id := c.Param("id")
	userID := c.GetUint("userID")

	var job db.Job
	if err := h.DB.First(&job, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Job not found"})
		return
	}

	// Check if user owns this job
	if job.CreatedBy != userID {
		// Check if user is admin
		isAdmin, exists := c.Get("isAdmin")
		if !exists || isAdmin != true {
			c.JSON(http.StatusForbidden, gin.H{"error": "You do not have permission to delete this job"})
			return
		}
	}

	// Start a transaction
	tx := h.DB.Begin()
	if tx.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to begin transaction"})
		return
	}

	// Create audit log before deletion
	auditDetails := map[string]interface{}{
		"name":              job.Name,
		"schedule":          job.Schedule,
		"enabled":           job.GetEnabled(),
		"config_ids":        job.GetConfigIDsList(),
		"webhook_enabled":   job.GetWebhookEnabled(),
		"notify_on_success": job.GetNotifyOnSuccess(),
		"notify_on_failure": job.GetNotifyOnFailure(),
	}

	auditLog := db.AuditLog{
		Action:     "delete",
		EntityType: "job",
		EntityID:   job.ID,
		UserID:     userID,
		Details:    auditDetails,
		Timestamp:  time.Now(),
	}

	if err := tx.Create(&auditLog).Error; err != nil {
		tx.Rollback()
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create audit log"})
		return
	}

	// Delete job
	if err := tx.Delete(&job).Error; err != nil {
		tx.Rollback()
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete job"})
		return
	}

	// Commit the transaction
	if err := tx.Commit().Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to commit transaction"})
		return
	}

	// Unschedule the job from the scheduler
	h.Scheduler.UnscheduleJob(job.ID)

	c.JSON(http.StatusOK, gin.H{"message": "Job deleted successfully"})
}

// HandleRunJob handles the POST /jobs/:id/run route
func (h *Handlers) HandleRunJob(c *gin.Context) {
	id := c.Param("id")
	userID := c.GetUint("userID")

	var job db.Job
	if err := h.DB.First(&job, id).Error; err != nil {
		c.Header("Content-Type", "text/html")
		c.String(http.StatusNotFound, "Job not found")
		return
	}

	// Check if user owns this job
	if job.CreatedBy != userID {
		// Check if user is admin
		isAdmin, exists := c.Get("isAdmin")
		if !exists || isAdmin != true {
			c.Header("Content-Type", "text/html")
			c.String(http.StatusForbidden, "You do not have permission to run this job")
			return
		}
	}

	// Determine job name for response
	jobName := job.Name
	if jobName == "" {
		// If job name is empty, try to get config name
		var config db.TransferConfig
		if err := h.DB.First(&config, job.ConfigID).Error; err == nil {
			jobName = config.Name
		} else {
			jobName = fmt.Sprintf("Job #%d", job.ID)
		}
	}

	// Create audit log for manual job run
	auditLog := db.AuditLog{
		Action:     "run_manual",
		EntityType: "job",
		EntityID:   job.ID,
		UserID:     userID,
		Details:    map[string]interface{}{"name": jobName, "job_id": job.ID},
		Timestamp:  time.Now(),
	}

	if err := h.DB.Create(&auditLog).Error; err != nil {
		log.Printf("HandleRunJob: Warning - Failed to create audit log: %v", err)
		// Continue anyway, as this is not critical to running the job
	}

	// Run the job immediately using the scheduler
	if err := h.Scheduler.RunJobNow(job.ID); err != nil {
		c.Header("Content-Type", "text/html")
		errorMsg := fmt.Sprintf("%s", err.Error())
		c.String(http.StatusInternalServerError, errorMsg)
		return
	}

	// Set custom header with job name for HTMX to use in the toast notification
	c.Header("HX-Job-Name", jobName)
	c.Header("Content-Type", "text/html")

	// Return HTML with JavaScript to trigger the notification
	successScript := fmt.Sprintf("Job \"%s\" has been started successfully", jobName)
	c.String(http.StatusOK, successScript)
}

// HandleDuplicateJob handles duplication of a job
func (h *Handlers) HandleDuplicateJob(c *gin.Context) {
	// Get the job ID from the URL
	idParam := c.Param("id")
	id, err := strconv.ParseUint(idParam, 10, 64)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid job ID"})
		return
	}

	userID := c.GetUint("userID")

	// Get the original job
	var originalJob db.Job
	if err := h.DB.First(&originalJob, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Job not found"})
		return
	}

	// Create a new job as a copy of the original
	newJob := originalJob
	newJob.ID = 0 // Reset ID to create a new record
	newJob.Name = originalJob.Name + " - Copy"
	newJob.CreatedAt = time.Now()
	newJob.UpdatedAt = time.Now()

	// Reset execution specific fields
	newJob.LastRun = nil
	newJob.NextRun = nil

	// Save the new job
	if err := h.DB.Create(&newJob).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create duplicate job: " + err.Error()})
		return
	}

	// If the job has associated configs, duplicate those associations
	configIDs := originalJob.GetConfigIDsList()
	if len(configIDs) > 0 {
		// Set the new job's config IDs
		newJob.SetConfigIDsList(configIDs)
		if err := h.DB.Save(&newJob).Error; err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update config associations: " + err.Error()})
			return
		}
	}

	// Create audit log entry
	auditDetails := map[string]interface{}{
		"name":              newJob.Name,
		"original_job_id":   originalJob.ID,
		"new_job_id":        newJob.ID,
		"schedule":          newJob.Schedule,
		"enabled":           newJob.GetEnabled(),
		"config_ids":        configIDs,
		"webhook_enabled":   newJob.GetWebhookEnabled(),
		"notify_on_success": newJob.GetNotifyOnSuccess(),
		"notify_on_failure": newJob.GetNotifyOnFailure(),
	}

	auditLog := db.AuditLog{
		Action:     "duplicate",
		EntityType: "job",
		EntityID:   newJob.ID,
		UserID:     userID,
		Details:    auditDetails,
		Timestamp:  time.Now(),
	}

	if err := h.DB.Create(&auditLog).Error; err != nil {
		log.Printf("Warning: Failed to create audit log for job duplication: %v", err)
		// Continue anyway, as this is not critical
	}

	// Schedule the job with the scheduler
	if err := h.Scheduler.ScheduleJob(&newJob); err != nil {
		log.Printf("Warning: Failed to schedule duplicated job: %v", err)
		// Continue anyway, as user can manually schedule later
	}

	// Redirect to jobs page
	c.Redirect(http.StatusFound, "/jobs")
}
