package shares

import (
	"net/http"

	"github.com/atlasos/calypso/internal/common/database"
	"github.com/atlasos/calypso/internal/common/logger"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
)

// Handler handles Shares-related API requests
type Handler struct {
	service *Service
	logger  *logger.Logger
}

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

// ListShares lists all shares
func (h *Handler) ListShares(c *gin.Context) {
	shares, err := h.service.ListShares(c.Request.Context())
	if err != nil {
		h.logger.Error("Failed to list shares", "error", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list shares"})
		return
	}

	// Ensure we return an empty array instead of null
	if shares == nil {
		shares = []*Share{}
	}

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

// GetShare retrieves a share by ID
func (h *Handler) GetShare(c *gin.Context) {
	shareID := c.Param("id")

	share, err := h.service.GetShare(c.Request.Context(), shareID)
	if err != nil {
		if err.Error() == "share not found" {
			c.JSON(http.StatusNotFound, gin.H{"error": "share not found"})
			return
		}
		h.logger.Error("Failed to get share", "error", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get share"})
		return
	}

	c.JSON(http.StatusOK, share)
}

// CreateShare creates a new share
func (h *Handler) CreateShare(c *gin.Context) {
	var req CreateShareRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		h.logger.Error("Invalid create share request", "error", err)
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request: " + err.Error()})
		return
	}

	// Validate request
	validate := validator.New()
	if err := validate.Struct(req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "validation failed: " + err.Error()})
		return
	}

	// Get user ID from context (set by auth middleware)
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
		return
	}

	share, err := h.service.CreateShare(c.Request.Context(), &req, userID.(string))
	if err != nil {
		if err.Error() == "dataset not found" {
			c.JSON(http.StatusNotFound, gin.H{"error": "dataset not found"})
			return
		}
		if err.Error() == "only filesystem datasets can be shared (not volumes)" {
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}
		if err.Error() == "at least one protocol (NFS or SMB) must be enabled" {
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}
		h.logger.Error("Failed to create share", "error", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, share)
}

// UpdateShare updates an existing share
func (h *Handler) UpdateShare(c *gin.Context) {
	shareID := c.Param("id")

	var req UpdateShareRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		h.logger.Error("Invalid update share request", "error", err)
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request: " + err.Error()})
		return
	}

	share, err := h.service.UpdateShare(c.Request.Context(), shareID, &req)
	if err != nil {
		if err.Error() == "share not found" {
			c.JSON(http.StatusNotFound, gin.H{"error": "share not found"})
			return
		}
		h.logger.Error("Failed to update share", "error", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, share)
}

// DeleteShare deletes a share
func (h *Handler) DeleteShare(c *gin.Context) {
	shareID := c.Param("id")

	err := h.service.DeleteShare(c.Request.Context(), shareID)
	if err != nil {
		if err.Error() == "share not found" {
			c.JSON(http.StatusNotFound, gin.H{"error": "share not found"})
			return
		}
		h.logger.Error("Failed to delete share", "error", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

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