package handler import ( "context" "strconv" "strings" "gcy_hpc_server/internal/model" "gcy_hpc_server/internal/server" "gcy_hpc_server/internal/service" "github.com/gin-gonic/gin" "go.uber.org/zap" ) type folderServiceProvider interface { CreateFolder(ctx context.Context, name string, parentID *int64) (*model.FolderResponse, error) GetFolder(ctx context.Context, id int64) (*model.FolderResponse, error) ListFolders(ctx context.Context, parentID *int64) ([]model.FolderResponse, error) DeleteFolder(ctx context.Context, id int64) error } type FolderHandler struct { svc folderServiceProvider logger *zap.Logger } func NewFolderHandler(svc *service.FolderService, logger *zap.Logger) *FolderHandler { return &FolderHandler{svc: svc, logger: logger} } func (h *FolderHandler) CreateFolder(c *gin.Context) { var req model.CreateFolderRequest if err := c.ShouldBindJSON(&req); err != nil { h.logger.Warn("invalid request body for create folder", zap.Error(err)) server.BadRequest(c, "invalid request body") return } if req.Name == "" { h.logger.Warn("missing folder name") server.BadRequest(c, "name is required") return } resp, err := h.svc.CreateFolder(c.Request.Context(), req.Name, req.ParentID) if err != nil { errStr := err.Error() if strings.Contains(errStr, "invalid folder name") || strings.Contains(errStr, "cannot be") { h.logger.Warn("invalid folder name", zap.String("name", req.Name), zap.Error(err)) server.BadRequest(c, errStr) return } h.logger.Error("failed to create folder", zap.Error(err)) server.InternalError(c, errStr) return } h.logger.Info("folder created", zap.Int64("id", resp.ID)) server.Created(c, resp) } func (h *FolderHandler) GetFolder(c *gin.Context) { id, err := strconv.ParseInt(c.Param("id"), 10, 64) if err != nil { h.logger.Warn("invalid folder id", zap.String("id", c.Param("id"))) server.BadRequest(c, "invalid id") return } resp, err := h.svc.GetFolder(c.Request.Context(), id) if err != nil { if strings.Contains(err.Error(), "not found") { h.logger.Warn("folder not found", zap.Int64("id", id)) server.NotFound(c, "folder not found") return } h.logger.Error("failed to get folder", zap.Int64("id", id), zap.Error(err)) server.InternalError(c, err.Error()) return } server.OK(c, resp) } func (h *FolderHandler) ListFolders(c *gin.Context) { var parentID *int64 if q := c.Query("parent_id"); q != "" { pid, err := strconv.ParseInt(q, 10, 64) if err != nil { h.logger.Warn("invalid parent_id query param", zap.String("parent_id", q)) server.BadRequest(c, "invalid parent_id") return } parentID = &pid } folders, err := h.svc.ListFolders(c.Request.Context(), parentID) if err != nil { h.logger.Error("failed to list folders", zap.Error(err)) server.InternalError(c, err.Error()) return } if folders == nil { folders = []model.FolderResponse{} } server.OK(c, folders) } func (h *FolderHandler) DeleteFolder(c *gin.Context) { id, err := strconv.ParseInt(c.Param("id"), 10, 64) if err != nil { h.logger.Warn("invalid folder id for delete", zap.String("id", c.Param("id"))) server.BadRequest(c, "invalid id") return } if err := h.svc.DeleteFolder(c.Request.Context(), id); err != nil { errStr := err.Error() if strings.Contains(errStr, "not empty") { h.logger.Warn("cannot delete non-empty folder", zap.Int64("id", id)) server.BadRequest(c, "folder is not empty") return } if strings.Contains(errStr, "not found") { h.logger.Warn("folder not found for delete", zap.Int64("id", id)) server.NotFound(c, "folder not found") return } h.logger.Error("failed to delete folder", zap.Int64("id", id), zap.Error(err)) server.InternalError(c, errStr) return } h.logger.Info("folder deleted", zap.Int64("id", id)) server.OK(c, gin.H{"message": "folder deleted"}) }