package tasks

import (
	"database/sql"
	"encoding/json"
	"net/http"
	"time"

	"github.com/atlasos/calypso/internal/common/database"
	"github.com/atlasos/calypso/internal/common/logger"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

// Handler handles task-related requests
type Handler struct {
	db     *database.DB
	logger *logger.Logger
}

// NewHandler creates a new task handler
func NewHandler(db *database.DB, log *logger.Logger) *Handler {
	return &Handler{
		db:     db,
		logger: log,
	}
}

// Task represents an async task
type Task struct {
	ID          string                 `json:"id"`
	Type        string                 `json:"type"`
	Status      string                 `json:"status"`
	Progress    int                    `json:"progress"`
	Message     string                 `json:"message"`
	ErrorMessage string                `json:"error_message,omitempty"`
	CreatedBy   string                 `json:"created_by,omitempty"`
	StartedAt   *time.Time             `json:"started_at,omitempty"`
	CompletedAt *time.Time             `json:"completed_at,omitempty"`
	CreatedAt   time.Time              `json:"created_at"`
	UpdatedAt   time.Time              `json:"updated_at"`
	Metadata    map[string]interface{} `json:"metadata,omitempty"`
}

// GetTask retrieves a task by ID
func (h *Handler) GetTask(c *gin.Context) {
	taskID := c.Param("id")

	// Validate UUID
	if _, err := uuid.Parse(taskID); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid task ID"})
		return
	}

	query := `
		SELECT id, type, status, progress, message, error_message,
		       created_by, started_at, completed_at, created_at, updated_at, metadata
		FROM tasks
		WHERE id = $1
	`

	var task Task
	var errorMsg, createdBy sql.NullString
	var startedAt, completedAt sql.NullTime
	var metadata sql.NullString

	err := h.db.QueryRow(query, taskID).Scan(
		&task.ID, &task.Type, &task.Status, &task.Progress,
		&task.Message, &errorMsg, &createdBy,
		&startedAt, &completedAt, &task.CreatedAt, &task.UpdatedAt, &metadata,
	)
	if err != nil {
		if err == sql.ErrNoRows {
			c.JSON(http.StatusNotFound, gin.H{"error": "task not found"})
			return
		}
		h.logger.Error("Failed to get task", "error", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get task"})
		return
	}

	if errorMsg.Valid {
		task.ErrorMessage = errorMsg.String
	}
	if createdBy.Valid {
		task.CreatedBy = createdBy.String
	}
	if startedAt.Valid {
		task.StartedAt = &startedAt.Time
	}
	if completedAt.Valid {
		task.CompletedAt = &completedAt.Time
	}
	if metadata.Valid && metadata.String != "" {
		json.Unmarshal([]byte(metadata.String), &task.Metadata)
	}

	c.JSON(http.StatusOK, task)
}

