package handlers import ( "errors" "fmt" "strings" "github.com/gofiber/fiber/v2" "wucher/internal/shared/pkg/attachmentresolver" "wucher/internal/transport/http/jsonapi" "wucher/internal/transport/http/response" ) func resolveAttachmentIDFromInput(c *fiber.Ctx, params attachmentresolver.Params, errorTitle string) ([]byte, bool) { attachmentID, err := attachmentresolver.Resolve(c.UserContext(), params) if err == nil { return attachmentID, false } var resolveErr *attachmentresolver.ResolveError if errors.As(err, &resolveErr) { switch resolveErr.Code { case attachmentresolver.ErrorInvalidAttachmentUUID: writeValidationError(c, fmt.Sprintf("%s is invalid UUID", fieldOrDefault(resolveErr.AttachmentField, "attachment_id")), "/data/attributes/"+fieldOrDefault(resolveErr.AttachmentField, "attachment_id")) return nil, true case attachmentresolver.ErrorInvalidFileUUID: writeValidationError(c, fmt.Sprintf("%s is invalid UUID", fieldOrDefault(resolveErr.FileField, "file_id")), "/data/attributes/"+fieldOrDefault(resolveErr.FileField, "file_id")) return nil, true case attachmentresolver.ErrorAttachmentNotFound: writeValidationError(c, fmt.Sprintf("%s not found", fieldOrDefault(resolveErr.AttachmentField, "attachment_id")), "/data/attributes/"+fieldOrDefault(resolveErr.AttachmentField, "attachment_id")) return nil, true case attachmentresolver.ErrorRequireValue: writeValidationError(c, fmt.Sprintf("%s or %s is required", fieldOrDefault(resolveErr.AttachmentField, "attachment_id"), fieldOrDefault(resolveErr.FileField, "file_id")), "/data/attributes") return nil, true case attachmentresolver.ErrorCannotResolveFromFile: writeValidationError(c, fmt.Sprintf("cannot resolve attachment from %s", fieldOrDefault(resolveErr.FileField, "file_id")), "/data/attributes/"+fieldOrDefault(resolveErr.FileField, "file_id")) return nil, true case attachmentresolver.ErrorFileNotReadyForAttachment: writeValidationError(c, fmt.Sprintf("%s is not ready yet; wait for file.updated SSE event", fieldOrDefault(resolveErr.FileField, "file_id")), "/data/attributes/"+fieldOrDefault(resolveErr.FileField, "file_id")) return nil, true case attachmentresolver.ErrorFileManagerUnavailable: writeBadRequestError(c, errorTitle, resolveErr.Error()) return nil, true } } writeBadRequestError(c, errorTitle, err.Error()) return nil, true } func writeValidationError(c *fiber.Ctx, detail, pointer string) { _ = response.WriteErrors(c, fiber.StatusUnprocessableEntity, []jsonapi.ErrorObject{{ Status: "422", Title: "Validation error", Detail: detail, Source: &jsonapi.ErrorSource{Pointer: pointer}, }}) } func writeBadRequestError(c *fiber.Ctx, title, detail string) { if title == "" { title = "Request failed" } _ = response.WriteErrors(c, fiber.StatusBadRequest, []jsonapi.ErrorObject{{ Status: "400", Title: title, Detail: detail, }}) } func fieldOrDefault(v string, fallback string) string { if v == "" { return fallback } return v } func hasNonEmptyOptionalString(v *string) bool { return v != nil && strings.TrimSpace(*v) != "" } func hasBlankOptionalString(v *string) bool { return v != nil && strings.TrimSpace(*v) == "" }