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