package handler import ( "context" "net/http" "strconv" "eslogad-be/internal/contract" "github.com/gin-gonic/gin" "github.com/google/uuid" ) type LetterService interface { CreateIncomingLetter(ctx context.Context, req *contract.CreateIncomingLetterRequest) (*contract.IncomingLetterResponse, error) GetIncomingLetterByID(ctx context.Context, id uuid.UUID) (*contract.IncomingLetterResponse, error) ListIncomingLetters(ctx context.Context, req *contract.ListIncomingLettersRequest) (*contract.ListIncomingLettersResponse, error) UpdateIncomingLetter(ctx context.Context, id uuid.UUID, req *contract.UpdateIncomingLetterRequest) (*contract.IncomingLetterResponse, error) SoftDeleteIncomingLetter(ctx context.Context, id uuid.UUID) error CreateDispositions(ctx context.Context, req *contract.CreateLetterDispositionRequest) (*contract.ListDispositionsResponse, error) ListDispositionsByLetter(ctx context.Context, letterID uuid.UUID) (*contract.ListDispositionsResponse, error) CreateDiscussion(ctx context.Context, letterID uuid.UUID, req *contract.CreateLetterDiscussionRequest) (*contract.LetterDiscussionResponse, error) UpdateDiscussion(ctx context.Context, letterID uuid.UUID, discussionID uuid.UUID, req *contract.UpdateLetterDiscussionRequest) (*contract.LetterDiscussionResponse, error) } type LetterHandler struct{ svc LetterService } func NewLetterHandler(svc LetterService) *LetterHandler { return &LetterHandler{svc: svc} } func (h *LetterHandler) CreateIncomingLetter(c *gin.Context) { var req contract.CreateIncomingLetterRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, &contract.ErrorResponse{Error: "invalid body", Code: http.StatusBadRequest}) return } resp, err := h.svc.CreateIncomingLetter(c.Request.Context(), &req) if err != nil { c.JSON(http.StatusInternalServerError, &contract.ErrorResponse{Error: err.Error(), Code: 500}) return } c.JSON(http.StatusCreated, contract.BuildSuccessResponse(resp)) } func (h *LetterHandler) GetIncomingLetter(c *gin.Context) { id, err := uuid.Parse(c.Param("id")) if err != nil { c.JSON(400, &contract.ErrorResponse{Error: "invalid id", Code: 400}) return } resp, err := h.svc.GetIncomingLetterByID(c.Request.Context(), id) if err != nil { c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500}) return } c.JSON(200, contract.BuildSuccessResponse(resp)) } func (h *LetterHandler) ListIncomingLetters(c *gin.Context) { page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10")) status := c.Query("status") query := c.Query("q") var statusPtr *string var queryPtr *string if status != "" { statusPtr = &status } if query != "" { queryPtr = &query } req := &contract.ListIncomingLettersRequest{Page: page, Limit: limit, Status: statusPtr, Query: queryPtr} resp, err := h.svc.ListIncomingLetters(c.Request.Context(), req) if err != nil { c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500}) return } c.JSON(200, contract.BuildSuccessResponse(resp)) } func (h *LetterHandler) UpdateIncomingLetter(c *gin.Context) { id, err := uuid.Parse(c.Param("id")) if err != nil { c.JSON(400, &contract.ErrorResponse{Error: "invalid id", Code: 400}) return } var req contract.UpdateIncomingLetterRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(400, &contract.ErrorResponse{Error: "invalid body", Code: 400}) return } resp, err := h.svc.UpdateIncomingLetter(c.Request.Context(), id, &req) if err != nil { c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500}) return } c.JSON(200, contract.BuildSuccessResponse(resp)) } func (h *LetterHandler) DeleteIncomingLetter(c *gin.Context) { id, err := uuid.Parse(c.Param("id")) if err != nil { c.JSON(400, &contract.ErrorResponse{Error: "invalid id", Code: 400}) return } if err := h.svc.SoftDeleteIncomingLetter(c.Request.Context(), id); err != nil { c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500}) return } c.JSON(200, &contract.SuccessResponse{Message: "deleted"}) } func (h *LetterHandler) CreateDispositions(c *gin.Context) { var req contract.CreateLetterDispositionRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(400, &contract.ErrorResponse{Error: "invalid body", Code: 400}) return } resp, err := h.svc.CreateDispositions(c.Request.Context(), &req) if err != nil { c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500}) return } c.JSON(201, contract.BuildSuccessResponse(resp)) } func (h *LetterHandler) ListDispositionsByLetter(c *gin.Context) { letterID, err := uuid.Parse(c.Param("letter_id")) if err != nil { c.JSON(400, &contract.ErrorResponse{Error: "invalid letter_id", Code: 400}) return } resp, err := h.svc.ListDispositionsByLetter(c.Request.Context(), letterID) if err != nil { c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500}) return } c.JSON(200, contract.BuildSuccessResponse(resp)) } func (h *LetterHandler) CreateDiscussion(c *gin.Context) { letterID, err := uuid.Parse(c.Param("letter_id")) if err != nil { c.JSON(400, &contract.ErrorResponse{Error: "invalid letter_id", Code: 400}) return } var req contract.CreateLetterDiscussionRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(400, &contract.ErrorResponse{Error: "invalid body", Code: 400}) return } resp, err := h.svc.CreateDiscussion(c.Request.Context(), letterID, &req) if err != nil { c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500}) return } c.JSON(201, contract.BuildSuccessResponse(resp)) } func (h *LetterHandler) UpdateDiscussion(c *gin.Context) { letterID, err := uuid.Parse(c.Param("letter_id")) if err != nil { c.JSON(400, &contract.ErrorResponse{Error: "invalid letter_id", Code: 400}) return } discussionID, err := uuid.Parse(c.Param("discussion_id")) if err != nil { c.JSON(400, &contract.ErrorResponse{Error: "invalid discussion_id", Code: 400}) return } var req contract.UpdateLetterDiscussionRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(400, &contract.ErrorResponse{Error: "invalid body", Code: 400}) return } resp, err := h.svc.UpdateDiscussion(c.Request.Context(), letterID, discussionID, &req) if err != nil { c.JSON(500, &contract.ErrorResponse{Error: err.Error(), Code: 500}) return } c.JSON(200, contract.BuildSuccessResponse(resp)) }