package handlers import ( "net/http" "strings" "gauth-central/internal/services" "github.com/gin-gonic/gin" "github.com/google/uuid" ) type PostCommentHandler struct { commentService *services.PostCommentService } func NewPostCommentHandler(commentService *services.PostCommentService) *PostCommentHandler { return &PostCommentHandler{commentService: commentService} } type CreatePostCommentRequest struct { Title string `json:"title" binding:"required"` Body string `json:"body" binding:"required"` ParentID *string `json:"parent_id"` IsActive *bool `json:"is_active"` } type UpdatePostCommentRequest struct { Title *string `json:"title"` Body *string `json:"body"` ParentID *string `json:"parent_id"` Slug *string `json:"slug"` IsActive *bool `json:"is_active"` } // GetPostCommentsByPostID godoc // @Summary Get active post comments // @Description Retrieve active comments for a post // @Tags post-comments // @Produce json // @Param id path string true "Post ID" // @Success 200 {array} models.PostComment // @Failure 500 {object} map[string]string // @Router /posts/{id}/comments [get] // GetPostCommentsByPostID returns active comments for a post. func (h *PostCommentHandler) GetPostCommentsByPostID(c *gin.Context) { postID := c.Param("id") items, err := h.commentService.GetPostCommentsByPostID(postID, true) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, items) } // CreatePostComment godoc // @Summary Create a post comment // @Description Create a new comment for a post (auth required) // @Tags post-comments // @Security ApiKeyAuth // @Accept json // @Produce json // @Param id path string true "Post ID" // @Param request body CreatePostCommentRequest true "Comment Request" // @Success 201 {object} models.PostComment // @Failure 400 {object} map[string]string // @Failure 401 {object} map[string]string // @Router /posts/{id}/comments [post] // CreatePostComment creates a comment for a post (auth required). func (h *PostCommentHandler) CreatePostComment(c *gin.Context) { userID := strings.TrimSpace(c.GetString("user_id")) if userID == "" { c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"}) return } userUUID, err := uuid.Parse(userID) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid user_id"}) return } postUUID, err := uuid.Parse(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid post_id"}) return } var req CreatePostCommentRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } var parentID *uuid.UUID if req.ParentID != nil { parsed, err := uuid.Parse(strings.TrimSpace(*req.ParentID)) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid parent_id"}) return } parentID = &parsed } isActive := true if req.IsActive != nil { isActive = *req.IsActive } item, err := h.commentService.CreatePostComment( userUUID, postUUID, req.Title, req.Body, parentID, isActive, ) if err != nil { status := http.StatusInternalServerError if err.Error() == "slug cannot be empty" || err.Error() == "slug already exists" { status = http.StatusBadRequest } c.JSON(status, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, item) } // AdminGetAllPostComments godoc // @Summary Get all post comments (Admin) // @Description Retrieve comments with optional post filter // @Tags admin // @Security ApiKeyAuth // @Produce json // @Param post_id query string false "Post ID" // @Success 200 {array} models.PostComment // @Failure 500 {object} map[string]string // @Router /admin/post-comments [get] // AdminGetAllPostComments returns comments with optional post filter. func (h *PostCommentHandler) AdminGetAllPostComments(c *gin.Context) { postID := strings.TrimSpace(c.Query("post_id")) var postIDPtr *string if postID != "" { postIDPtr = &postID } items, err := h.commentService.GetAllPostComments(postIDPtr, false) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, items) } // AdminGetPostCommentByID godoc // @Summary Get post comment by ID (Admin) // @Description Retrieve a post comment by ID // @Tags admin // @Security ApiKeyAuth // @Produce json // @Param id path string true "Comment ID" // @Success 200 {object} models.PostComment // @Failure 404 {object} map[string]string // @Router /admin/post-comments/{id} [get] // AdminGetPostCommentByID returns a comment by ID. func (h *PostCommentHandler) AdminGetPostCommentByID(c *gin.Context) { id := c.Param("id") item, err := h.commentService.GetPostCommentByID(id) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, item) } // AdminUpdatePostComment godoc // @Summary Update a post comment (Admin) // @Description Update an existing post comment // @Tags admin // @Security ApiKeyAuth // @Accept json // @Produce json // @Param id path string true "Comment ID" // @Param request body UpdatePostCommentRequest true "Comment Request" // @Success 200 {object} models.PostComment // @Failure 400 {object} map[string]string // @Failure 404 {object} map[string]string // @Router /admin/post-comments/{id} [put] // AdminUpdatePostComment updates a comment. func (h *PostCommentHandler) AdminUpdatePostComment(c *gin.Context) { id := c.Param("id") var req UpdatePostCommentRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } parentIDSet := false var parentIDPtr *uuid.UUID if req.ParentID != nil { parentIDSet = true if strings.TrimSpace(*req.ParentID) == "" { parentIDPtr = nil } else { parsed, err := uuid.Parse(strings.TrimSpace(*req.ParentID)) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid parent_id"}) return } parentIDPtr = &parsed } } item, err := h.commentService.UpdatePostComment( id, req.Title, req.Body, parentIDPtr, parentIDSet, req.Slug, req.IsActive, ) if err != nil { status := http.StatusInternalServerError switch err.Error() { case "post comment not found": status = http.StatusNotFound case "slug cannot be empty", "slug already exists": status = http.StatusBadRequest } c.JSON(status, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, item) } // AdminDeletePostComment godoc // @Summary Delete a post comment (Admin) // @Description Delete a post comment by ID // @Tags admin // @Security ApiKeyAuth // @Param id path string true "Comment ID" // @Success 200 {object} map[string]string // @Failure 404 {object} map[string]string // @Router /admin/post-comments/{id} [delete] // AdminDeletePostComment deletes a comment. func (h *PostCommentHandler) AdminDeletePostComment(c *gin.Context) { id := c.Param("id") if err := h.commentService.DeletePostComment(id); err != nil { c.JSON(http.StatusNotFound, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "Post comment deleted successfully"}) }