package projects

import (
	"errors"
	"net/http"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"senlinai-agent/backend/internal/httpx"
	"senlinai-agent/backend/internal/logic/auth"
	"senlinai-agent/backend/internal/models"
)

// TagHandler 单独承载项目内标签接口，避免项目核心 handler 混入对象写职责。
type TagHandler struct {
	service *Service
}

// NewTagHandler 创建项目标签 HTTP registrar。
func NewTagHandler(service *Service) *TagHandler {
	return &TagHandler{service: service}
}

// Register 注册项目范围内的标签读写接口。
func (h *TagHandler) Register(router gin.IRouter) {
	router.GET("/projects/:id/tags", h.list)
	router.POST("/projects/:id/tags", h.create)
}

func (h *TagHandler) list(c *gin.Context) {
	userID, project, ok := ownedProjectFromRequest(c)
	if !ok {
		return
	}
	tags, err := h.service.ListProjectTags(userID, project.ID)
	if err != nil {
		writeProjectError(c, err)
		return
	}
	result := make([]WorkspaceTagDTO, 0, len(tags))
	for _, tag := range tags {
		result = append(result, WorkspaceTagDTO{ID: tag.Identity, Name: tag.Name})
	}
	c.JSON(http.StatusOK, result)
}

func (h *TagHandler) create(c *gin.Context) {
	userID, project, ok := ownedProjectFromRequest(c)
	if !ok {
		return
	}
	var input struct {
		Name string `json:"name"`
	}
	if err := c.ShouldBindJSON(&input); err != nil {
		httpx.Error(c, http.StatusBadRequest, "invalid_request", "请求参数无效")
		return
	}
	tag, err := h.service.CreateProjectTag(userID, project.ID, input.Name)
	if err != nil {
		writeTagError(c, err)
		return
	}
	c.JSON(http.StatusCreated, WorkspaceTagDTO{ID: tag.Identity, Name: tag.Name})
}

func writeTagError(c *gin.Context, err error) {
	switch {
	case errors.Is(err, ErrTagNameRequired):
		httpx.Error(c, http.StatusBadRequest, "invalid_request", "标签名称不能为空")
	case errors.Is(err, gorm.ErrRecordNotFound):
		httpx.Error(c, http.StatusNotFound, "not_found", "项目不存在")
	default:
		httpx.Error(c, http.StatusInternalServerError, "internal_error", "标签创建失败")
	}
}

func ownedProjectFromRequest(c *gin.Context) (uint, *models.SenlinAgentProject, bool) {
	userID, ok := auth.CurrentUserID(c)
	if !ok {
		httpx.Error(c, http.StatusUnauthorized, "unauthorized", "未登录或登录已失效")
		return 0, nil, false
	}
	identity, ok := httpx.IdentityParam(c, "id")
	if !ok {
		return 0, nil, false
	}
	// 标签接口先以 owner_id + identity 锁定项目，避免形成全局标签或越权读写。
	project, err := FindOwnedProject(userID, identity)
	if err != nil {
		writeProjectError(c, err)
		return 0, nil, false
	}
	return userID, project, true
}
