package handlers import ( "net/http" "time" "github.com/gin-gonic/gin" "github.com/google/uuid" "go.uber.org/zap" apperrors "veza-backend-api/internal/errors" "veza-backend-api/internal/models" "veza-backend-api/internal/services" ) // GearHandler handles gear inventory HTTP requests type GearHandler struct { gearService *services.GearService logger *zap.Logger } // NewGearHandler creates a new GearHandler func NewGearHandler(gearService *services.GearService, logger *zap.Logger) *GearHandler { return &GearHandler{gearService: gearService, logger: logger} } // CreateGearItemRequest represents the request body for creating a gear item type CreateGearItemRequest struct { Name string `json:"name" binding:"required"` Category string `json:"category"` Brand string `json:"brand"` Model string `json:"model"` SerialNumber string `json:"serialNumber"` Image string `json:"image"` Images []string `json:"images"` Status string `json:"status"` Condition string `json:"condition"` PurchaseDate *time.Time `json:"purchaseDate"` PurchasePrice float64 `json:"purchasePrice"` Currency string `json:"currency"` Vendor string `json:"vendor"` OrderNumber string `json:"orderNumber"` WarrantyExpire *time.Time `json:"warrantyExpire"` WarrantyType string `json:"warrantyType"` SupportContact string `json:"supportContact"` Specs map[string]interface{} `json:"specs"` Notes string `json:"notes"` Documents []map[string]interface{} `json:"documents"` MaintenanceHistory []map[string]interface{} `json:"maintenanceHistory"` } // UpdateGearItemRequest represents the request body for updating a gear item type UpdateGearItemRequest struct { Name *string `json:"name"` Category *string `json:"category"` Brand *string `json:"brand"` Model *string `json:"model"` SerialNumber *string `json:"serialNumber"` Image *string `json:"image"` Images []string `json:"images"` Status *string `json:"status"` Condition *string `json:"condition"` PurchaseDate *time.Time `json:"purchaseDate"` PurchasePrice *float64 `json:"purchasePrice"` Currency *string `json:"currency"` Vendor *string `json:"vendor"` OrderNumber *string `json:"orderNumber"` WarrantyExpire *time.Time `json:"warrantyExpire"` WarrantyType *string `json:"warrantyType"` SupportContact *string `json:"supportContact"` Specs map[string]interface{} `json:"specs"` Notes *string `json:"notes"` Documents []map[string]interface{} `json:"documents"` MaintenanceHistory []map[string]interface{} `json:"maintenanceHistory"` } func reqToModel(req *CreateGearItemRequest) *models.GearItem { item := &models.GearItem{ Name: req.Name, Category: req.Category, Brand: req.Brand, Model: req.Model, Status: req.Status, Condition: req.Condition, Currency: req.Currency, Vendor: req.Vendor, Notes: req.Notes, Specs: req.Specs, Documents: req.Documents, MaintenanceHistory: req.MaintenanceHistory, } if req.Status == "" { item.Status = "Active" } if req.Condition == "" { item.Condition = "Good" } if req.Currency == "" { item.Currency = "USD" } if req.SerialNumber != "" { item.SerialNumber = req.SerialNumber } if req.Image != "" { item.Image = req.Image } if len(req.Images) > 0 { item.Images = req.Images } if req.PurchaseDate != nil { item.PurchaseDate = req.PurchaseDate } item.PurchasePrice = req.PurchasePrice if req.OrderNumber != "" { item.OrderNumber = req.OrderNumber } if req.WarrantyExpire != nil { item.WarrantyExpire = req.WarrantyExpire } if req.WarrantyType != "" { item.WarrantyType = req.WarrantyType } if req.SupportContact != "" { item.SupportContact = req.SupportContact } return item } func applyUpdate(item *models.GearItem, req *UpdateGearItemRequest) { if req.Name != nil { item.Name = *req.Name } if req.Category != nil { item.Category = *req.Category } if req.Brand != nil { item.Brand = *req.Brand } if req.Model != nil { item.Model = *req.Model } if req.SerialNumber != nil { item.SerialNumber = *req.SerialNumber } if req.Image != nil { item.Image = *req.Image } if req.Images != nil { item.Images = req.Images } if req.Status != nil { item.Status = *req.Status } if req.Condition != nil { item.Condition = *req.Condition } if req.PurchaseDate != nil { item.PurchaseDate = req.PurchaseDate } if req.PurchasePrice != nil { item.PurchasePrice = *req.PurchasePrice } if req.Currency != nil { item.Currency = *req.Currency } if req.Vendor != nil { item.Vendor = *req.Vendor } if req.OrderNumber != nil { item.OrderNumber = *req.OrderNumber } if req.WarrantyExpire != nil { item.WarrantyExpire = req.WarrantyExpire } if req.WarrantyType != nil { item.WarrantyType = *req.WarrantyType } if req.SupportContact != nil { item.SupportContact = *req.SupportContact } if req.Specs != nil { item.Specs = req.Specs } if req.Notes != nil { item.Notes = *req.Notes } if req.Documents != nil { item.Documents = req.Documents } if req.MaintenanceHistory != nil { item.MaintenanceHistory = req.MaintenanceHistory } } // ListGear returns all gear items for the authenticated user func (h *GearHandler) ListGear(c *gin.Context) { userID, ok := GetUserIDUUID(c) if !ok { return } items, err := h.gearService.List(c.Request.Context(), userID) if err != nil { RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to list gear", err)) return } RespondSuccess(c, http.StatusOK, gin.H{"items": items}) } // GetGear returns a single gear item by ID func (h *GearHandler) GetGear(c *gin.Context) { userID, ok := GetUserIDUUID(c) if !ok { return } id, err := uuid.Parse(c.Param("id")) if err != nil { RespondWithAppError(c, apperrors.NewValidationError("invalid gear item ID")) return } item, err := h.gearService.Get(c.Request.Context(), id, userID) if err != nil { RespondWithAppError(c, apperrors.NewNotFoundError("gear item not found")) return } RespondSuccess(c, http.StatusOK, gin.H{"item": item}) } // CreateGear creates a new gear item func (h *GearHandler) CreateGear(c *gin.Context) { userID, ok := GetUserIDUUID(c) if !ok { return } var req CreateGearItemRequest if appErr := h.commonHandler().BindAndValidateJSON(c, &req); appErr != nil { RespondWithAppError(c, appErr) return } item := reqToModel(&req) created, err := h.gearService.Create(c.Request.Context(), userID, item) if err != nil { RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to create gear item", err)) return } RespondSuccess(c, http.StatusCreated, gin.H{"item": created}) } // UpdateGear updates an existing gear item func (h *GearHandler) UpdateGear(c *gin.Context) { userID, ok := GetUserIDUUID(c) if !ok { return } id, err := uuid.Parse(c.Param("id")) if err != nil { RespondWithAppError(c, apperrors.NewValidationError("invalid gear item ID")) return } var req UpdateGearItemRequest if appErr := h.commonHandler().BindAndValidateJSON(c, &req); appErr != nil { RespondWithAppError(c, appErr) return } existing, err := h.gearService.Get(c.Request.Context(), id, userID) if err != nil { RespondWithAppError(c, apperrors.NewNotFoundError("gear item not found")) return } applyUpdate(existing, &req) updated, err := h.gearService.Update(c.Request.Context(), id, userID, existing) if err != nil { RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to update gear item", err)) return } RespondSuccess(c, http.StatusOK, gin.H{"item": updated}) } // DeleteGear deletes a gear item func (h *GearHandler) DeleteGear(c *gin.Context) { userID, ok := GetUserIDUUID(c) if !ok { return } id, err := uuid.Parse(c.Param("id")) if err != nil { RespondWithAppError(c, apperrors.NewValidationError("invalid gear item ID")) return } if err := h.gearService.Delete(c.Request.Context(), id, userID); err != nil { RespondWithAppError(c, apperrors.NewNotFoundError("gear item not found")) return } RespondSuccess(c, http.StatusOK, gin.H{"message": "gear item deleted"}) } func (h *GearHandler) commonHandler() *CommonHandler { return NewCommonHandler(h.logger) }