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"
)

// ClientHandler handles client-related operations
type ClientHandler struct {
	service *services.ClientService
}

// NewClientHandler creates a new ClientHandler
func NewClientHandler(service *services.ClientService) *ClientHandler {
	return &ClientHandler{
		service: service,
	}
}

// RegisterRoutes registers routes for client operations
func (h *ClientHandler) RegisterRoutes(r *gin.RouterGroup) {
	r.GET("/", h.ListClients)
	r.POST("/", h.CreateClient)
	r.GET("/:id", h.GetClient)
	r.PUT("/:id", h.UpdateClient)
	r.DELETE("/:id", h.DeleteClient)
	r.GET("/:id/deployments", h.GetClientDeployments)
}

// ListClients returns all clients
func (h *ClientHandler) ListClients(c *gin.Context) {
	clients, err := h.service.ListClients(nil)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("Failed to fetch clients: %v", err)})
		return
	}

	c.JSON(http.StatusOK, clients)
}

// CreateClient creates a new client
func (h *ClientHandler) CreateClient(c *gin.Context) {
	var client models.Client

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

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

	c.JSON(http.StatusCreated, client)
}

// GetClient returns a specific client
func (h *ClientHandler) GetClient(c *gin.Context) {
	id := c.Param("id")

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

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

	c.JSON(http.StatusOK, client)
}

// UpdateClient updates a client
func (h *ClientHandler) UpdateClient(c *gin.Context) {
	id := c.Param("id")

	// Parse updated client data
	var updatedClient models.Client
	if err := c.ShouldBindJSON(&updatedClient); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body"})
		return
	}

	// Set the ID to ensure it matches the URL parameter
	updatedClient.ID = id

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

	c.JSON(http.StatusOK, updatedClient)
}

// DeleteClient deletes a client
func (h *ClientHandler) DeleteClient(c *gin.Context) {
	id := c.Param("id")

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

	c.Status(http.StatusNoContent)
}

// GetClientDeployments returns all deployments for a client
func (h *ClientHandler) GetClientDeployments(c *gin.Context) {
	id := c.Param("id")

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

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

	// TODO: Retrieve deployments - this likely requires a separate repository or service
	// For now, return an empty list
	deployments := []models.Deployment{}

	c.JSON(http.StatusOK, deployments)
}
