package handler import ( "encoding/json" "errors" "net/http" "strings" "5803025048/W04/internal/middleware" "5803025048/W04/internal/models" "5803025048/W04/internal/store" "github.com/google/uuid" ) type SnippetHandler struct { snippetStore SnippetStore } func NewSnippetHandler(snippetStore SnippetStore) *SnippetHandler { return &SnippetHandler{snippetStore: snippetStore} } type snippetRequest struct { Title string `json:"title"` Content string `json:"content"` } func snippetID(r *http.Request) string { id := r.PathValue("id") if id == "" { path := strings.TrimPrefix(r.URL.Path, "/snippets/") id = strings.TrimSuffix(path, "/") } return id } func (h *SnippetHandler) Create(w http.ResponseWriter, r *http.Request) { userID := middleware.GetUserID(r.Context()) if userID == "" { writeError(w, http.StatusUnauthorized, "Unauthorized") return } var req snippetRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "Bad Request") return } req.Title = strings.TrimSpace(req.Title) req.Content = strings.TrimSpace(req.Content) if req.Title == "" || req.Content == "" { writeError(w, http.StatusBadRequest, "Title and content are required") return } snippet := &models.Snippet{ ID: uuid.New().String(), Title: req.Title, Content: req.Content, UserID: userID, } if err := h.snippetStore.Create(r.Context(), snippet); err != nil { writeError(w, http.StatusInternalServerError, "Internal Server Error") return } writeJSON(w, http.StatusCreated, snippet) } func (h *SnippetHandler) List(w http.ResponseWriter, r *http.Request) { userID := middleware.GetUserID(r.Context()) if userID == "" { writeError(w, http.StatusUnauthorized, "Unauthorized") return } snippets, err := h.snippetStore.GetByUserID(r.Context(), userID) if err != nil { writeError(w, http.StatusInternalServerError, "Internal Server Error") return } if snippets == nil { // Pastikan selalu "[]", bukan "null". snippets = []*models.Snippet{} } writeJSON(w, http.StatusOK, snippets) } func (h *SnippetHandler) Get(w http.ResponseWriter, r *http.Request) { id := snippetID(r) if id == "" { writeError(w, http.StatusBadRequest, "Bad Request") return } snippet, err := h.snippetStore.GetByID(r.Context(), id) if err != nil { if errors.Is(err, store.ErrNotFound) { writeError(w, http.StatusNotFound, "Snippet not found") return } writeError(w, http.StatusInternalServerError, "Internal Server Error") return } writeJSON(w, http.StatusOK, snippet) } func (h *SnippetHandler) Delete(w http.ResponseWriter, r *http.Request) { userID := middleware.GetUserID(r.Context()) if userID == "" { writeError(w, http.StatusUnauthorized, "Unauthorized") return } id := snippetID(r) if id == "" { writeError(w, http.StatusBadRequest, "Bad Request") return } snippet, err := h.snippetStore.GetByID(r.Context(), id) if err != nil { if errors.Is(err, store.ErrNotFound) { writeError(w, http.StatusNotFound, "Snippet not found") return } writeError(w, http.StatusInternalServerError, "Internal Server Error") return } if snippet.UserID != userID { writeError(w, http.StatusForbidden, "Forbidden") return } if err := h.snippetStore.Delete(r.Context(), id); err != nil { if errors.Is(err, store.ErrNotFound) { writeError(w, http.StatusNotFound, "Snippet not found") return } writeError(w, http.StatusInternalServerError, "Internal Server Error") return } w.WriteHeader(http.StatusNoContent) }