package repositories import ( "errors" "lost-and-found/internal/models" "gorm.io/gorm" ) type LostItemRepository struct { db *gorm.DB } func NewLostItemRepository(db *gorm.DB) *LostItemRepository { return &LostItemRepository{db: db} } // Create creates a new lost item report func (r *LostItemRepository) Create(lostItem *models.LostItem) error { return r.db.Create(lostItem).Error } // FindByID finds lost item by ID func (r *LostItemRepository) FindByID(id uint) (*models.LostItem, error) { var lostItem models.LostItem err := r.db.Preload("Category").Preload("User").Preload("User.Role").First(&lostItem, id).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("lost item not found") } return nil, err } return &lostItem, nil } // FindAll returns all lost items with filters func (r *LostItemRepository) FindAll(page, limit int, status, category, search string, userID *uint) ([]models.LostItem, int64, error) { var lostItems []models.LostItem var total int64 query := r.db.Model(&models.LostItem{}) // Filter by user if specified if userID != nil { query = query.Where("user_id = ?", *userID) } // Apply filters if status != "" { query = query.Where("status = ?", status) } if category != "" { query = query.Joins("JOIN categories ON categories.id = lost_items.category_id").Where("categories.slug = ?", category) } if search != "" { query = query.Where("name ILIKE ? OR description ILIKE ?", "%"+search+"%", "%"+search+"%") } // Count total if err := query.Count(&total).Error; err != nil { return nil, 0, err } // Get paginated results offset := (page - 1) * limit err := query.Preload("Category").Preload("User").Preload("User.Role"). Order("date_lost DESC"). Offset(offset).Limit(limit).Find(&lostItems).Error if err != nil { return nil, 0, err } return lostItems, total, nil } // Update updates lost item data func (r *LostItemRepository) Update(lostItem *models.LostItem) error { return r.db.Save(lostItem).Error } // UpdateStatus updates lost item status func (r *LostItemRepository) UpdateStatus(id uint, status string) error { return r.db.Model(&models.LostItem{}).Where("id = ?", id).Update("status", status).Error } // Delete soft deletes a lost item func (r *LostItemRepository) Delete(id uint) error { return r.db.Delete(&models.LostItem{}, id).Error } // FindByUser finds lost items by user ID func (r *LostItemRepository) FindByUser(userID uint, page, limit int) ([]models.LostItem, int64, error) { var lostItems []models.LostItem var total int64 query := r.db.Model(&models.LostItem{}).Where("user_id = ?", userID) // Count total if err := query.Count(&total).Error; err != nil { return nil, 0, err } // Get paginated results offset := (page - 1) * limit err := query.Preload("Category").Order("date_lost DESC"). Offset(offset).Limit(limit).Find(&lostItems).Error if err != nil { return nil, 0, err } return lostItems, total, nil } // CountByStatus counts lost items by status func (r *LostItemRepository) CountByStatus(status string) (int64, error) { var count int64 err := r.db.Model(&models.LostItem{}).Where("status = ?", status).Count(&count).Error return count, err } // FindActiveForMatching finds active lost items for matching func (r *LostItemRepository) FindActiveForMatching(categoryID uint) ([]models.LostItem, error) { var lostItems []models.LostItem err := r.db.Where("status = ? AND category_id = ?", models.LostItemStatusActive, categoryID). Preload("User").Find(&lostItems).Error return lostItems, err }