package controllers import ( "lost-and-found/internal/models" "lost-and-found/internal/services" "lost-and-found/internal/utils" "net/http" "strconv" "github.com/gin-gonic/gin" "gorm.io/gorm" ) type ItemController struct { itemService *services.ItemService matchService *services.MatchService } func NewItemController(db *gorm.DB) *ItemController { return &ItemController{ itemService: services.NewItemService(db), matchService: services.NewMatchService(db), } } // GetAllItems gets all items (public) // GET /api/items func (c *ItemController) GetAllItems(ctx *gin.Context) { page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1")) limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10")) status := ctx.Query("status") category := ctx.Query("category") search := ctx.Query("search") items, total, err := c.itemService.GetAllItems(page, limit, status, category, search) if err != nil { utils.ErrorResponse(ctx, http.StatusInternalServerError, "Failed to get items", err.Error()) return } utils.SendPaginatedResponse(ctx, http.StatusOK, "Items retrieved", items, total, page, limit) } // GetItemByID gets item by ID // GET /api/items/:id func (c *ItemController) GetItemByID(ctx *gin.Context) { id, err := strconv.ParseUint(ctx.Param("id"), 10, 32) if err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid item ID", err.Error()) return } // Check if user is manager or admin isManager := false if userObj, exists := ctx.Get("user"); exists { user := userObj.(*models.User) isManager = user.IsManager() || user.IsAdmin() } item, err := c.itemService.GetItemByID(uint(id), isManager) if err != nil { utils.ErrorResponse(ctx, http.StatusNotFound, "Item not found", err.Error()) return } utils.SuccessResponse(ctx, http.StatusOK, "Item retrieved", item) } // CreateItem creates a new item // POST /api/items func (c *ItemController) CreateItem(ctx *gin.Context) { userObj, _ := ctx.Get("user") user := userObj.(*models.User) var req services.CreateItemRequest if err := ctx.ShouldBindJSON(&req); err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid request data", err.Error()) return } ipAddress := ctx.ClientIP() userAgent := ctx.Request.UserAgent() item, err := c.itemService.CreateItem(user.ID, req, ipAddress, userAgent) if err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to create item", err.Error()) return } // Auto-match with lost items go c.matchService.AutoMatchNewItem(item.ID) utils.SuccessResponse(ctx, http.StatusCreated, "Item created", item.ToDetailResponse()) } // UpdateItem updates an item // PUT /api/items/:id func (c *ItemController) UpdateItem(ctx *gin.Context) { userObj, _ := ctx.Get("user") user := userObj.(*models.User) itemID, err := strconv.ParseUint(ctx.Param("id"), 10, 32) if err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid item ID", err.Error()) return } var req services.UpdateItemRequest if err := ctx.ShouldBindJSON(&req); err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid request data", err.Error()) return } ipAddress := ctx.ClientIP() userAgent := ctx.Request.UserAgent() item, err := c.itemService.UpdateItem(user.ID, uint(itemID), req, ipAddress, userAgent) if err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to update item", err.Error()) return } utils.SuccessResponse(ctx, http.StatusOK, "Item updated", item.ToDetailResponse()) } // UpdateItemStatus updates item status // PATCH /api/items/:id/status func (c *ItemController) UpdateItemStatus(ctx *gin.Context) { userObj, _ := ctx.Get("user") user := userObj.(*models.User) itemID, err := strconv.ParseUint(ctx.Param("id"), 10, 32) if err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid item ID", err.Error()) return } var req struct { Status string `json:"status" binding:"required"` } if err := ctx.ShouldBindJSON(&req); err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid request data", err.Error()) return } ipAddress := ctx.ClientIP() userAgent := ctx.Request.UserAgent() if err := c.itemService.UpdateItemStatus(user.ID, uint(itemID), req.Status, ipAddress, userAgent); err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to update status", err.Error()) return } utils.SuccessResponse(ctx, http.StatusOK, "Item status updated", nil) } // DeleteItem deletes an item // DELETE /api/items/:id func (c *ItemController) DeleteItem(ctx *gin.Context) { userObj, _ := ctx.Get("user") user := userObj.(*models.User) itemID, err := strconv.ParseUint(ctx.Param("id"), 10, 32) if err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid item ID", err.Error()) return } ipAddress := ctx.ClientIP() userAgent := ctx.Request.UserAgent() if err := c.itemService.DeleteItem(user.ID, uint(itemID), ipAddress, userAgent); err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Failed to delete item", err.Error()) return } utils.SuccessResponse(ctx, http.StatusOK, "Item deleted", nil) } // GetItemsByReporter gets items by reporter // GET /api/user/items func (c *ItemController) GetItemsByReporter(ctx *gin.Context) { userObj, _ := ctx.Get("user") user := userObj.(*models.User) page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1")) limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10")) items, total, err := c.itemService.GetItemsByReporter(user.ID, page, limit) if err != nil { utils.ErrorResponse(ctx, http.StatusInternalServerError, "Failed to get items", err.Error()) return } var responses []models.ItemDetailResponse for _, item := range items { responses = append(responses, item.ToDetailResponse()) } utils.SendPaginatedResponse(ctx, http.StatusOK, "Items retrieved", responses, total, page, limit) } // GetItemRevisionHistory gets revision history for an item // GET /api/items/:id/revisions func (c *ItemController) GetItemRevisionHistory(ctx *gin.Context) { itemID, err := strconv.ParseUint(ctx.Param("id"), 10, 32) if err != nil { utils.ErrorResponse(ctx, http.StatusBadRequest, "Invalid item ID", err.Error()) return } page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1")) limit, _ := strconv.Atoi(ctx.DefaultQuery("limit", "10")) revisions, total, err := c.itemService.GetItemRevisionHistory(uint(itemID), page, limit) if err != nil { utils.ErrorResponse(ctx, http.StatusInternalServerError, "Failed to get revision history", err.Error()) return } utils.SendPaginatedResponse(ctx, http.StatusOK, "Revision history retrieved", revisions, total, page, limit) }