package handlers

import (
	"net/http"

	"gauth-central/internal/services"

	"github.com/gin-gonic/gin"
)

type TagHandler struct {
	tagService *services.TagService
}

func NewTagHandler(tagService *services.TagService) *TagHandler {
	return &TagHandler{tagService: tagService}
}

type CreateTagRequest struct {
	Tag      string `json:"tag" binding:"required"`
	IsActive *bool  `json:"is_active"` // Pointer to allow false value
}

type UpdateTagRequest struct {
	Tag      string `json:"tag"`
	IsActive *bool  `json:"is_active"`
}

// GetAllTags godoc
// @Summary Get all tags
// @Description Retrieve a list of all tags. Public endpoint returns only active tags. Admin endpoint returns all.
// @Tags tags
// @Produce json
// @Success 200 {array} models.Tag
// @Failure 500 {object} map[string]string
// @Router /tags [get]
func (h *TagHandler) GetAllTags(c *gin.Context) {
	// Check if user is admin to decide whether to show all or only active
	// For simplicity in this public endpoint, we'll just return active ones
	// Admin specific endpoint can be added separately or controlled via query param + auth check

	// Let's assume public access gets only active tags
	tags, err := h.tagService.GetAllTags(true)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, tags)
}

// AdminGetAllTags godoc
// @Summary Get all tags (Admin)
// @Description Retrieve a list of all tags including inactive ones
// @Tags admin
// @Security ApiKeyAuth
// @Produce json
// @Success 200 {array} models.Tag
// @Failure 500 {object} map[string]string
// @Router /admin/tags [get]
func (h *TagHandler) AdminGetAllTags(c *gin.Context) {
	tags, err := h.tagService.GetAllTags(false)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, tags)
}

// CreateTag godoc
// @Summary Create a new tag (Admin)
// @Description Create a new tag
// @Tags admin
// @Security ApiKeyAuth
// @Accept json
// @Produce json
// @Param request body CreateTagRequest true "Tag Request"
// @Success 201 {object} models.Tag
// @Failure 400 {object} map[string]string
// @Router /admin/tags [post]
func (h *TagHandler) CreateTag(c *gin.Context) {
	var req CreateTagRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	isActive := true
	if req.IsActive != nil {
		isActive = *req.IsActive
	}

	tag, err := h.tagService.CreateTag(req.Tag, isActive)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusCreated, tag)
}

// UpdateTag godoc
// @Summary Update a tag (Admin)
// @Description Update an existing tag
// @Tags admin
// @Security ApiKeyAuth
// @Accept json
// @Produce json
// @Param id path string true "Tag ID"
// @Param request body UpdateTagRequest true "Tag Request"
// @Success 200 {object} models.Tag
// @Failure 400 {object} map[string]string
// @Failure 404 {object} map[string]string
// @Router /admin/tags/{id} [put]
func (h *TagHandler) UpdateTag(c *gin.Context) {
	id := c.Param("id")
	var req UpdateTagRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	tag, err := h.tagService.UpdateTag(id, req.Tag, req.IsActive)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, tag)
}

// DeleteTag godoc
// @Summary Delete a tag (Admin)
// @Description Delete a tag by ID
// @Tags admin
// @Security ApiKeyAuth
// @Param id path string true "Tag ID"
// @Success 200 {object} map[string]string
// @Failure 404 {object} map[string]string
// @Router /admin/tags/{id} [delete]
func (h *TagHandler) DeleteTag(c *gin.Context) {
	id := c.Param("id")
	if err := h.tagService.DeleteTag(id); err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"message": "Tag deleted successfully"})
}

// GetTagByID godoc
// @Summary Get a tag by ID (Admin)
// @Description Retrieve details of a specific tag
// @Tags admin
// @Security ApiKeyAuth
// @Produce json
// @Param id path string true "Tag ID"
// @Success 200 {object} models.Tag
// @Failure 404 {object} map[string]string
// @Router /admin/tags/{id} [get]
func (h *TagHandler) GetTagByID(c *gin.Context) {
	id := c.Param("id")
	tag, err := h.tagService.GetTagByID(id)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, tag)
}
