# CouchDB Service Guide

This guide provides comprehensive documentation for the CouchDB service implementation in the Adopt-a-Street application.

## Overview

The `CouchDBService` class provides a production-ready interface for interacting with CouchDB, replacing MongoDB as the primary database. It includes connection management, CRUD operations, query helpers, and migration utilities.

## Configuration

### Environment Variables

Add these to your `.env` file:

```bash
# CouchDB Configuration
COUCHDB_URL=http://localhost:5984
COUCHDB_DB_NAME=adopt-a-street
```

### Connection Initialization

```javascript
const couchdbService = require('./services/couchdbService');

// Initialize the service (call once at application startup)
await couchdbService.initialize();

// Check if connected
if (couchdbService.isReady()) {
  console.log('CouchDB is ready');
}
```

## Core Features

### 1. Connection Management

- **Automatic connection**: Establishes connection on first use
- **Database creation**: Creates database if it doesn't exist
- **Health checks**: Validates connection status
- **Graceful shutdown**: Properly closes connections

### 2. Design Documents & Indexes

The service automatically creates design documents with:

- **Views**: For common query patterns
- **Mango Indexes**: For efficient document queries
- **Geospatial indexes**: For location-based queries

#### Available Indexes

- `user-by-email`: Fast user authentication
- `users-by-points`: Leaderboard queries
- `streets-by-location`: Geospatial street searches
- `streets-by-status`: Filter streets by adoption status
- `posts-by-date`: Social feed ordering
- `events-by-date-status`: Event management
- `reports-by-status`: Report workflow management

### 3. Generic CRUD Operations

```javascript
// Create document
const doc = {
  _id: 'user_123',
  type: 'user',
  name: 'John Doe',
  email: 'john@example.com'
};
const created = await couchdbService.createDocument(doc);

// Get document
const retrieved = await couchdbService.getDocument('user_123');

// Update document
created.name = 'Jane Doe';
const updated = await couchdbService.updateDocument(created);

// Delete document
await couchdbService.deleteDocument('user_123', updated._rev);
```

### 4. Query Operations

```javascript
// Find with Mango query
const users = await couchdbService.find({
  selector: {
    type: 'user',
    points: { $gt: 100 }
  },
  sort: [{ points: 'desc' }],
  limit: 10
});

// Find single document
const user = await couchdbService.findOne({
  type: 'user',
  email: 'john@example.com'
});

// Find by type
const streets = await couchdbService.findByType('street', {
  status: 'available'
});

// Use views
const topUsers = await couchdbService.view('users', 'by-points', {
  limit: 10,
  descending: true
});
```

### 5. Batch Operations

```javascript
// Bulk create/update
const docs = [
  { _id: 'doc1', type: 'test', name: 'Test 1' },
  { _id: 'doc2', type: 'test', name: 'Test 2' }
];
const result = await couchdbService.bulkDocs({ docs });
```

### 6. Specialized Helper Methods

#### User Operations

```javascript
// Find user by email
const user = await couchdbService.findUserByEmail('john@example.com');

// Update user points with transaction
const updatedUser = await couchdbService.updateUserPoints(
  'user_123', 
  50, 
  'Completed task: Clean up street',
  {
    entityType: 'Task',
    entityId: 'task_456',
    entityName: 'Clean up street'
  }
);
```

#### Street Operations

```javascript
// Find streets by location (geospatial)
const bounds = [[-74.1, 40.6], [-73.9, 40.8]]; // NYC area
const streets = await couchdbService.findStreetsByLocation(bounds);

// Adopt a street
const adoptedStreet = await couchdbService.adoptStreet('user_123', 'street_456');
```

#### Task Operations

```javascript
// Complete a task
const completedTask = await couchdbService.completeTask('user_123', 'task_789');
```

#### Social Features

```javascript
// Create a post
const post = await couchdbService.createPost('user_123', {
  content: 'Great day cleaning up!',
  imageUrl: 'https://example.com/image.jpg',
  cloudinaryPublicId: 'post_123'
});

// Toggle like on post
const updatedPost = await couchdbService.togglePostLike('user_123', 'post_456');

// Add comment
const comment = await couchdbService.addCommentToPost(
  'user_123', 
  'post_456', 
  'Great work! 🎉'
);
```

#### Event Management

```javascript
// Join event
const updatedEvent = await couchdbService.joinEvent('user_123', 'event_789');
```

#### Leaderboard & Activity

```javascript
// Get leaderboard
const leaderboard = await couchdbService.getLeaderboard(10);

// Get user activity feed
const activity = await couchdbService.getUserActivity('user_123', 20);

// Get social feed
const feed = await couchdbService.getSocialFeed(20, 0);
```

#### Report Management

```javascript
// Create report
const report = await couchdbService.createReport('user_123', 'street_456', {
  issue: 'Broken streetlight',
  imageUrl: 'https://example.com/report.jpg',
  cloudinaryPublicId: 'report_123'
});

// Resolve report
const resolved = await couchdbService.resolveReport('report_789');
```

## Document Structure

### User Document

```javascript
{
  _id: "user_1234567890abcdef",
  type: "user",
  name: "John Doe",
  email: "john@example.com",
  password: "hashed_password",
  isPremium: false,
  points: 150,
  profilePicture: "https://cloudinary.com/image.jpg",
  cloudinaryPublicId: "abc123",
  adoptedStreets: ["street_abc123", "street_def456"],
  completedTasks: ["task_123", "task_456"],
  posts: ["post_789", "post_012"],
  events: ["event_345", "event_678"],
  earnedBadges: [
    {
      badgeId: "badge_123",
      name: "Street Hero",
      description: "Adopted 5 streets",
      icon: "🏆",
      rarity: "rare",
      earnedAt: "2024-01-15T10:30:00Z",
      progress: 100
    }
  ],
  stats: {
    streetsAdopted: 2,
    tasksCompleted: 5,
    postsCreated: 3,
    eventsParticipated: 2,
    badgesEarned: 1
  },
  createdAt: "2024-01-01T00:00:00Z",
  updatedAt: "2024-01-15T10:30:00Z"
}
```

### Street Document

```javascript
{
  _id: "street_abc123def456",
  type: "street",
  name: "Main Street",
  location: {
    type: "Point",
    coordinates: [-74.0060, 40.7128]
  },
  adoptedBy: {
    userId: "user_1234567890abcdef",
    name: "John Doe",
    profilePicture: "https://cloudinary.com/image.jpg"
  },
  status: "adopted",
  stats: {
    tasksCount: 5,
    completedTasksCount: 3,
    reportsCount: 2,
    openReportsCount: 1
  },
  createdAt: "2024-01-01T00:00:00Z",
  updatedAt: "2024-01-15T10:30:00Z"
}
```

## Migration

### Running the Migration

```bash
# From the backend directory
node scripts/migrate-to-couchdb.js
```

### Migration Process

1. **Phase 1**: Export and transform all MongoDB documents to CouchDB format
2. **Phase 2**: Resolve relationships and populate embedded data
3. **Phase 3**: Calculate statistics and counters

### Migration Features

- **ID transformation**: MongoDB ObjectIds → prefixed string IDs
- **Relationship resolution**: Populates embedded user/street data
- **Statistics calculation**: Computes counts and aggregates
- **Error handling**: Continues migration even if some documents fail
- **Progress tracking**: Shows migration status and statistics

## Error Handling

The service provides comprehensive error handling:

```javascript
try {
  const doc = await couchdbService.getDocument('nonexistent');
  if (!doc) {
    console.log('Document not found');
  }
} catch (error) {
  console.error('Database error:', error.message);
}
```

### Common Error Scenarios

1. **Connection errors**: Service will retry and provide clear error messages
2. **Document conflicts**: Use `resolveConflict()` method for handling
3. **Validation errors**: Use `validateDocument()` before operations
4. **Query errors**: Detailed error messages for invalid queries

## Performance Considerations

### Index Usage

- Always use indexed fields in selectors
- Use appropriate limit/sort combinations
- Consider view queries for complex aggregations

### Batch Operations

- Use `bulkDocs()` for multiple document operations
- Batch size recommendations: 100-500 documents per operation

### Memory Management

- Service maintains single connection instance
- Automatic cleanup on shutdown
- Efficient document streaming for large datasets

## Testing

### Running Tests

```bash
# Run CouchDB service tests
bun test __tests__/services/couchdbService.test.js
```

### Test Coverage

- Connection management
- CRUD operations
- Query functionality
- Helper methods
- Error handling
- Migration utilities

## Best Practices

### 1. Document Design

- Include `type` field in all documents
- Use consistent ID prefixes (`user_`, `street_`, etc.)
- Embed frequently accessed data
- Keep document sizes reasonable (< 1MB)

### 2. Query Optimization

- Use appropriate indexes
- Limit result sets with pagination
- Prefer views for complex queries
- Use selectors efficiently

### 3. Error Handling

- Always wrap database calls in try-catch
- Check for null returns from `getDocument()`
- Handle conflicts gracefully
- Log errors for debugging

### 4. Performance

- Use batch operations for bulk changes
- Implement proper pagination
- Cache frequently accessed data
- Monitor query performance

## Integration with Existing Code

### Replacing MongoDB Operations

```javascript
// Before (MongoDB)
const user = await User.findOne({ email: 'john@example.com' });

// After (CouchDB)
const user = await couchdbService.findUserByEmail('john@example.com');
```

### Updating Routes

Most route handlers can be updated by replacing Mongoose calls with CouchDB service methods:

```javascript
// Example route update
router.get('/users/:id', async (req, res) => {
  try {
    const user = await couchdbService.getDocument(`user_${req.params.id}`);
    if (!user) {
      return res.status(404).json({ msg: 'User not found' });
    }
    res.json(user);
  } catch (error) {
    console.error(error.message);
    res.status(500).send('Server error');
  }
});
```

## Monitoring & Maintenance

### Health Checks

The service provides connection status monitoring:

```javascript
if (couchdbService.isReady()) {
  // Database is available
} else {
  // Handle database unavailability
}
```

### Performance Monitoring

- Monitor query response times
- Track document sizes
- Watch for connection pool issues
- Monitor index usage

## Troubleshooting

### Common Issues

1. **Connection refused**: Check CouchDB server status
2. **Database not found**: Service creates automatically
3. **Index not found**: Service creates design documents on init
4. **Document conflicts**: Use conflict resolution methods

### Debug Mode

Enable debug logging by setting environment variable:

```bash
DEBUG=couchdb* node server.js
```

## Future Enhancements

### Planned Features

1. **Change feed integration**: Real-time updates
2. **Replication support**: Multi-instance deployment
3. **Advanced analytics**: Complex aggregations
4. **Caching layer**: Redis integration
5. **Connection pooling**: High-performance scaling

### Extensibility

The service is designed to be easily extended:

```javascript
// Add custom helper methods
couchdbService.customMethod = async function(params) {
  // Custom implementation
};
```

## Conclusion

The CouchDB service provides a robust, production-ready replacement for MongoDB in the Adopt-a-Street application. It offers comprehensive functionality, proper error handling, and migration tools to ensure a smooth transition.

For questions or issues, refer to the test files and implementation details in `backend/services/couchdbService.js`.