package handlers import ( "errors" "net/http" "strconv" "github.com/gin-gonic/gin" "github.com/treytartt/mycrib-api/internal/dto/requests" "github.com/treytartt/mycrib-api/internal/middleware" "github.com/treytartt/mycrib-api/internal/models" "github.com/treytartt/mycrib-api/internal/services" ) // DocumentHandler handles document-related HTTP requests type DocumentHandler struct { documentService *services.DocumentService } // NewDocumentHandler creates a new document handler func NewDocumentHandler(documentService *services.DocumentService) *DocumentHandler { return &DocumentHandler{documentService: documentService} } // ListDocuments handles GET /api/documents/ func (h *DocumentHandler) ListDocuments(c *gin.Context) { user := c.MustGet(middleware.AuthUserKey).(*models.User) response, err := h.documentService.ListDocuments(user.ID) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, response) } // GetDocument handles GET /api/documents/:id/ func (h *DocumentHandler) GetDocument(c *gin.Context) { user := c.MustGet(middleware.AuthUserKey).(*models.User) documentID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid document ID"}) return } response, err := h.documentService.GetDocument(uint(documentID), user.ID) if err != nil { switch { case errors.Is(err, services.ErrDocumentNotFound): c.JSON(http.StatusNotFound, gin.H{"error": err.Error()}) case errors.Is(err, services.ErrDocumentAccessDenied): c.JSON(http.StatusForbidden, gin.H{"error": err.Error()}) default: c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) } return } c.JSON(http.StatusOK, response) } // ListWarranties handles GET /api/documents/warranties/ func (h *DocumentHandler) ListWarranties(c *gin.Context) { user := c.MustGet(middleware.AuthUserKey).(*models.User) response, err := h.documentService.ListWarranties(user.ID) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, response) } // CreateDocument handles POST /api/documents/ func (h *DocumentHandler) CreateDocument(c *gin.Context) { user := c.MustGet(middleware.AuthUserKey).(*models.User) var req requests.CreateDocumentRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } response, err := h.documentService.CreateDocument(&req, user.ID) if err != nil { if errors.Is(err, services.ErrResidenceAccessDenied) { c.JSON(http.StatusForbidden, gin.H{"error": err.Error()}) return } c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, response) } // UpdateDocument handles PUT/PATCH /api/documents/:id/ func (h *DocumentHandler) UpdateDocument(c *gin.Context) { user := c.MustGet(middleware.AuthUserKey).(*models.User) documentID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid document ID"}) return } var req requests.UpdateDocumentRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } response, err := h.documentService.UpdateDocument(uint(documentID), user.ID, &req) if err != nil { switch { case errors.Is(err, services.ErrDocumentNotFound): c.JSON(http.StatusNotFound, gin.H{"error": err.Error()}) case errors.Is(err, services.ErrDocumentAccessDenied): c.JSON(http.StatusForbidden, gin.H{"error": err.Error()}) default: c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) } return } c.JSON(http.StatusOK, response) } // DeleteDocument handles DELETE /api/documents/:id/ func (h *DocumentHandler) DeleteDocument(c *gin.Context) { user := c.MustGet(middleware.AuthUserKey).(*models.User) documentID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid document ID"}) return } err = h.documentService.DeleteDocument(uint(documentID), user.ID) if err != nil { switch { case errors.Is(err, services.ErrDocumentNotFound): c.JSON(http.StatusNotFound, gin.H{"error": err.Error()}) case errors.Is(err, services.ErrDocumentAccessDenied): c.JSON(http.StatusForbidden, gin.H{"error": err.Error()}) default: c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) } return } c.JSON(http.StatusOK, gin.H{"message": "Document deleted successfully"}) } // ActivateDocument handles POST /api/documents/:id/activate/ func (h *DocumentHandler) ActivateDocument(c *gin.Context) { user := c.MustGet(middleware.AuthUserKey).(*models.User) documentID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid document ID"}) return } response, err := h.documentService.ActivateDocument(uint(documentID), user.ID) if err != nil { switch { case errors.Is(err, services.ErrDocumentNotFound): c.JSON(http.StatusNotFound, gin.H{"error": err.Error()}) case errors.Is(err, services.ErrDocumentAccessDenied): c.JSON(http.StatusForbidden, gin.H{"error": err.Error()}) default: c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) } return } c.JSON(http.StatusOK, gin.H{"message": "Document activated", "document": response}) } // DeactivateDocument handles POST /api/documents/:id/deactivate/ func (h *DocumentHandler) DeactivateDocument(c *gin.Context) { user := c.MustGet(middleware.AuthUserKey).(*models.User) documentID, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid document ID"}) return } response, err := h.documentService.DeactivateDocument(uint(documentID), user.ID) if err != nil { switch { case errors.Is(err, services.ErrDocumentNotFound): c.JSON(http.StatusNotFound, gin.H{"error": err.Error()}) case errors.Is(err, services.ErrDocumentAccessDenied): c.JSON(http.StatusForbidden, gin.H{"error": err.Error()}) default: c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) } return } c.JSON(http.StatusOK, gin.H{"message": "Document deactivated", "document": response}) }