package handlers

import (
	"fmt"
	"net/http"

	"git.linuxforward.com/byop/byop-engine/models"
	"git.linuxforward.com/byop/byop-engine/services"
	"github.com/gin-gonic/gin"
)

// ComponentHandler handles component-related operations
type ComponentHandler struct {
	service *services.ComponentService
}

// NewComponentHandler creates a new ComponentHandler
func NewComponentHandler(service *services.ComponentService) *ComponentHandler {
	return &ComponentHandler{
		service: service,
	}
}

// RegisterRoutes registers routes for component operations
func (h *ComponentHandler) RegisterRoutes(r *gin.RouterGroup) {
	r.GET("/", h.ListComponents)
	r.POST("/", h.CreateComponent)
	r.GET("/:id", h.GetComponent)
	r.PUT("/:id", h.UpdateComponent)
	r.DELETE("/:id", h.DeleteComponent)
	r.GET("/:id/deployments", h.GetComponentDeployments)
}

// ListComponents returns all components with optional filtering
func (h *ComponentHandler) ListComponents(c *gin.Context) {
	filter := make(map[string]interface{})

	// Attempt to bind query parameters, but allow empty filters
	if err := c.ShouldBindQuery(&filter); err != nil && len(filter) > 0 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid query parameters"})
		return
	}

	components, err := h.service.ListComponents(filter)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to list components: %v", err)})
		return
	}

	c.JSON(http.StatusOK, components)
}

// CreateComponent creates a new component
func (h *ComponentHandler) CreateComponent(c *gin.Context) {
	var component models.Component

	if err := c.ShouldBindJSON(&component); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("Invalid request body: %v", err)})
		return
	}

	// Get the user ID from the context (set by auth middleware)
	userID, exists := c.Get("userID")
	if exists {
		component.CreatedBy = userID.(string)
	}

	if err := h.service.CreateComponent(&component); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to create component: %v", err)})
		return
	}

	c.JSON(http.StatusCreated, component)
}

// GetComponent returns a specific component
func (h *ComponentHandler) GetComponent(c *gin.Context) {
	id := c.Param("id")

	component, err := h.service.GetComponent(id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to fetch component: %v", err)})
		return
	}

	if component == nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Component not found"})
		return
	}

	c.JSON(http.StatusOK, component)
}

// UpdateComponent updates a component
func (h *ComponentHandler) UpdateComponent(c *gin.Context) {
	id := c.Param("id")

	var updatedComponent models.Component
	if err := c.ShouldBindJSON(&updatedComponent); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("Invalid request body: %v", err)})
		return
	}

	// Ensure the ID matches the URL parameter
	updatedComponent.ID = id

	if err := h.service.UpdateComponent(&updatedComponent); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to update component: %v", err)})
		return
	}

	c.JSON(http.StatusOK, updatedComponent)
}

// DeleteComponent deletes a component
func (h *ComponentHandler) DeleteComponent(c *gin.Context) {
	id := c.Param("id")

	if err := h.service.DeleteComponent(id); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to delete component: %v", err)})
		return
	}

	c.Status(http.StatusNoContent)
}

// GetComponentDeployments returns all deployments for a component
func (h *ComponentHandler) GetComponentDeployments(c *gin.Context) {
	id := c.Param("id")

	deployments, err := h.service.GetComponentDeployments(id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to fetch component deployments: %v", err)})
		return
	}

	c.JSON(http.StatusOK, deployments)
}
