# Indexable Implementation (Refactored)

## Overview

This package provides a refactored implementation of the `indexable.DB` interface that uses `mutil.GetObjects` for better consistency with the existing codebase. The implementation has been moved to the mongo folder and includes a factory for project indexable in the pkg/db folder.

## Structure

### 1. `api/pkg/db/internal/mongo/indexable/indexable.go`
- **`ReorderTemplate[T]`**: Generic template function that uses `mutil.GetObjects` for fetching objects
- **`IndexableDB`**: Base struct for creating concrete implementations
- **Type-safe implementation**: Uses Go generics with proper type constraints

### 2. `api/pkg/db/project_indexable.go`
- **`ProjectIndexableDB`**: Factory implementation for Project objects
- **`NewProjectIndexableDB`**: Constructor function
- **`ReorderTemplate`**: Duplicate of the mongo version for convenience

## Key Changes from Previous Implementation

### 1. **Uses `mutil.GetObjects`**
```go
// Old implementation (manual cursor handling)
err = repo.FindManyByFilter(ctx, filter, func(cursor *mongo.Cursor) error {
    var obj T
    if err := cursor.Decode(&obj); err != nil {
        return err
    }
    objects = append(objects, obj)
    return nil
})

// New implementation (using mutil.GetObjects)
objects, err := mutil.GetObjects[T](
    ctx,
    logger,
    filterFunc().
        And(
            repository.IndexOpFilter(minIdx, builder.Gte),
            repository.IndexOpFilter(maxIdx, builder.Lte),
        ),
    nil, nil, nil, // limit, offset, isArchived
    repo,
)
```

### 2. **Moved to Mongo Folder**
- Location: `api/pkg/db/internal/mongo/indexable/`
- Consistent with other mongo implementations
- Better organization within the codebase

### 3. **Added Factory in pkg/db**
- Location: `api/pkg/db/project_indexable.go`
- Provides easy access to project indexable functionality
- Includes logger parameter for better error handling

## Usage

### Using the Factory (Recommended)

```go
import "github.com/tech/sendico/pkg/db"

// Create a project indexable DB
projectDB := db.NewProjectIndexableDB(repo, logger, organizationRef)

// Reorder a project
err := projectDB.Reorder(ctx, projectID, newIndex)
if err != nil {
    // Handle error
}
```

### Using the Template Directly

```go
import "github.com/tech/sendico/pkg/db/internal/mongo/indexable"

// Define helper functions
getIndexable := func(p *model.Project) *model.Indexable {
    return &p.Indexable
}

updateIndexable := func(p *model.Project, newIndex int) {
    p.Index = newIndex
}

createEmpty := func() *model.Project {
    return &model.Project{}
}

filterFunc := func() builder.Query {
    return repository.OrgFilter(organizationRef)
}

// Use the template
err := indexable.ReorderTemplate(
    ctx,
    logger,
    repo,
    objectRef,
    newIndex,
    filterFunc,
    getIndexable,
    updateIndexable,
    createEmpty,
)
```

## Benefits of Refactoring

1. **Consistency**: Uses `mutil.GetObjects` like other parts of the codebase
2. **Better Error Handling**: Includes logger parameter for proper error logging
3. **Organization**: Moved to appropriate folder structure
4. **Factory Pattern**: Easy-to-use factory for common use cases
5. **Type Safety**: Maintains compile-time type checking
6. **Performance**: Leverages existing optimized `mutil.GetObjects` implementation

## Testing

### Mongo Implementation Tests
```bash
go test ./db/internal/mongo/indexable -v
```

### Factory Tests
```bash
go test ./db -v
```

## Integration

The refactored implementation is ready for integration with existing project reordering APIs. The factory pattern makes it easy to add reordering functionality to any service that needs to reorder projects within an organization.

## Migration from Old Implementation

If you were using the old implementation:

1. **Update imports**: Change from `api/pkg/db/internal/indexable` to `api/pkg/db`
2. **Use factory**: Replace manual template usage with `NewProjectIndexableDB`
3. **Add logger**: Include a logger parameter in your constructor calls
4. **Update tests**: Use the new test structure if needed

The API remains the same, so existing code should work with minimal changes. 