# AI Development Guidelines for Municipal Backend

## Overview
This document provides rules and guidelines for AI assistants working on the Municipal Backend project to ensure consistency, security, and maintainability.

---

## Core Principles

### 1. Code Quality Standards
- **Always use ES6+ syntax** with proper imports/exports
- **Follow existing naming conventions**: camelCase for variables, PascalCase for classes/models
- **Add proper error handling** with try-catch blocks and meaningful error messages
- **Write clean, readable code** with appropriate comments where logic is complex
- **Maintain existing code patterns** and architectural decisions

### 2. Security Requirements
- **Never expose sensitive data** (passwords, tokens, secrets) in logs or responses
- **Always validate user input** using existing validators or adding new ones
- **Use proper authentication middleware** on protected routes
- **Sanitize database queries** to prevent injection attacks
- **Implement proper CORS policies** and security headers

### 3. Database Operations
- **Always use Mongoose models** from the `/models` directory
- **Handle database errors gracefully** with appropriate HTTP status codes
- **Optimize queries** with proper indexes and lean operations where possible
- **Never return raw MongoDB documents** - use `.lean()` or `.select()` for performance
- **Always check models first** before creating or modifying controllers
- **IMPORTANT: Always verify with user before making changes to models**

### 4. API Design Rules
- **Follow RESTful conventions** for HTTP methods and status codes
- **Use consistent response format**: `{ success: true/false, data: { records , pagination , message: '...' }`
- **Use `sanitizeParams`** to clean request body when required (removes empty strings, null, undefined)
- **Use `paramsValidator`** when validating **3 or more required parameters**
  ```javascript
  // Example usage:
  import { sanitizeParams } from '../../utils/sanitizeParams.js';
  import paramsValidator from '../../utils/paramsValidator.js';
  
  req.body = sanitizeParams(req.body);
  const isValidated = paramsValidator(req.body, ['title', 'description', 'category']);
  if (!isValidated.success) {
    return res.status(400).json({ success: false, message: isValidated.message });
  }
  ```

### 5. File Structure Guidelines

**IMPORTANT: Admin and User/Mobile controllers are SEPARATE and should NOT be confused.**

| Type | Path | Purpose |
|------|------|---------|
| **Admin Controllers** | `/src/controllers/admin/` | Admin panel operations |
| **User/Mobile Controllers** | `/src/controllers/mobile/` | Mobile app/citizen operations 
| **Admin Routes** | `/src/routes/admin/routes.js` | Admin API routes |
| **User Routes** | `/src/routes/user/routes.js` | User/Mobile API routes | 
| **Models** | `/models/` | Database schemas and static methods |
| **Utils** | `/src/utils/` | Reusable helper functions |

### 6. Error Handling Standards
- **Always use**: `error.message || 'Fallback message'`
- **Admin controllers**: Return `error.message` in response for debugging
  ```javascript
  res.status(500).json({ success: false, message: error?.message || 'Failed to...' });
  ```
- **User/Mobile controllers**: Return generic fallback messages (don't expose internal errors)
  ```javascript
  res.status(500).json({ success: false, message: 'Failed to fetch data' });
  ```
- **Log errors appropriately** with context and user information
- **Use appropriate HTTP status codes** (400, 401, 403, 404, 500)

### 7. File Upload & Media Storage

#### Multer
- **Use multer** for handling multipart/form-data (images, videos, documents)
- Multer is configured with **memory storage** — files arrive as `req.file.buffer` or `req.files[].buffer`
- Multer configurations are in `/src/config/multer.js`
- Example route with multer:
  ```javascript
  router.post('/tourism', multer.uploadTourismImages, tourismController.createTourismPlace);
  ```

#### Media Storage Utility (`src/utils/mediaStorage.js`)
- **NEW standard for all file storage** — use this for all new features
- Writes files to disk inside the `media/` folder as real files (`.jpg`, `.mp4`, `.pdf`, etc.)
- **Do NOT store file buffers or base64 in MongoDB** — store only the `relativePath` string in DB
- The `Attachment` model (which stores binary buffers) exists in older features and will be migrated later — **do not use it for new features**

**Available functions:**
```javascript
import { uploadFile, getFile, deleteFile, updateFile } from '../../utils/mediaStorage.js';

// Upload
const result = await uploadFile({
  folders: ['public', 'tourism', 'images'],  // nested folder path
  fileBuffer: req.file.buffer,
  originalName: req.file.originalname,
  mimeType: req.file.mimetype,
  size: req.file.size,
});
// result.relativePath → save this in DB  e.g. "public/tourism/images/lake_a7k2m3f.jpg"

// Delete (idempotent — won't throw if file missing)
await deleteFile({ relativePath: savedPath });

// Update (deletes old, uploads new)
const result = await updateFile({ oldRelativePath: savedPath, folders: [...], fileBuffer, originalName, mimeType, size });

// Get info / check existence
const info = await getFile({ relativePath: savedPath });
// info.exists, info.fullPath, info.size
```

#### Public vs Private files
Files are split into two sub-folders:

| Sub-folder | URL accessible | Use for |
|-----------|---------------|---------|
| `media/public/...` | ✅ Yes — `GET /media/public/<path>` | Tourism images, blog images, health education, member profiles |
| `media/private/...` | 🔒 No — needs auth route | Complaint attachments, doctor slips, seller KYC documents |

**`express.static` only serves `media/public/`** — private files are never exposed publicly.

```javascript
// Public upload — accessible via URL directly
await uploadFile({ folders: ['public', 'tourism', 'images'], ... });
// URL: http://host/media/public/tourism/images/lake_a7k2m3f.jpg

// Private upload — only accessible through an auth-protected route
await uploadFile({ folders: ['private', 'complaints'], ... });
```

**Minimal DB fields to store per file:**
```javascript
{
  relativePath: { type: String },   // "public/tourism/images/lake_a7k2m3f.jpg"
  originalName: { type: String },   // "lake photo.jpg"
  mimeType:     { type: String },   // "image/jpeg"
  size:         { type: Number },   // 102400
}
```

### 8. Performance Guidelines
- **Implement pagination** for all fetch/list requests
- **Optimize database queries** with proper indexing
- **Use connection pooling** for database operations
- **Monitor API response times** and optimize bottlenecks

---

## Pagination Patterns

### Admin Pagination (Page-based)
**Request format:**
```javascript
{ search, status, page = 1, limit = 15, ...filters }
```

**Response format:**
```javascript
{
  success: true,
  data: {
    <records>,  // e.g., blogs, complaints, places
    pagination: { page: parsedPage, limit: parsedLimit, total }
  }
}
```

**Implementation:**
```javascript
const { search, status, page = 1, limit = 15 } = req.body;
const parsedPage = parseInt(page);
const parsedLimit = parseInt(limit);

if (isNaN(parsedPage) || isNaN(parsedLimit) || parsedPage < 1 || parsedLimit < 1 || parsedLimit > 100) {
  return res.status(400).json({ success: false, message: 'Invalid page or limit.' });
}

const skip = (parsedPage - 1) * parsedLimit;
const [records, total] = await Promise.all([
  Model.find(query).skip(skip).limit(parsedLimit),
  Model.countDocuments(query),
]);

res.json({
  success: true,
  data: { records, pagination: { page: parsedPage, limit: parsedLimit, total } },
});
```

### User/Mobile Pagination (Offset-based)
**Request format:**
```javascript
{ search, category, offset = 0, limit = 20, ...filters }
```

**Response format:**
```javascript
{
  success: true,
  data: {
    <records>,  // e.g., blogs, tourismPlaces, complaints
    pagination: { offset: parsedOffset, limit: parsedLimit, total }
  }
}
```

**Implementation:**
```javascript
const { search, category, offset = 0, limit = 20 } = req.body;
const parsedOffset = parseInt(offset);
const parsedLimit = parseInt(limit);

if (isNaN(parsedOffset) || isNaN(parsedLimit) || parsedOffset < 0 || parsedLimit < 1 || parsedLimit > 20) {
  return res.status(400).json({
    success: false,
    message: 'Invalid offset or limit. Offset must be >= 0, limit must be between 1 and 20.',
  });
}

const [records, total] = await Promise.all([
  Model.find(query).skip(parsedOffset).limit(parsedLimit),
  Model.countDocuments(query),
]);

res.json({
  success: true,
  data: { records, pagination: { offset: parsedOffset, limit: parsedLimit, total } },
});
```

---

## Route Status Convention

### Routes marked with `//done`
- These routes follow the correct pattern and are production-ready
- Use these as reference for implementing new features
- **Example:**
  ```javascript
  router.post('/get-complaints', complaintsController.getComplaints); //done
  router.get('/complaint/:id', complaintsController.getComplaintById);//done
  ```

### Routes WITHOUT `//done`
- These are **old scaffold routes** that don't follow the current pattern
- **Must be rewritten** when working on them
- Consider them as templates that need updating
- Follow the `//done` routes as examples for the correct implementation

---

## Specific Rules for This Project

### User Management
- **Always verify user roles** before allowing privileged operations
- **Use proper session management** with JWT tokens
- **Admin auth middleware**: `adminAuthMiddleware`
- **User auth middleware**: `citizenAuthMiddleware`

---

## Code Review Checklist

### Before Submitting Code
- [ ] Code follows existing patterns from `//done` routes
- [ ] All inputs are properly validated (sanitizeParams + paramsValidator)
- [ ] Error handling uses correct pattern (admin vs user)
- [ ] Pagination follows correct pattern (page-based for admin, offset-based for user)
- [ ] Database operations are optimized
- [ ] API responses are consistent with existing format
- [ ] Models checked before controller changes

---

## Development Workflow

### 1. Before Making Changes
- Check if route is marked `//done` - if yes, follow that pattern
- If route is NOT marked `//done` - rewrite following `//done` patterns
- **Always check models first** before creating/modifying controllers
- **Ask user before modifying models**

### 2. Understanding Requirements
- Read existing `//done` controllers to understand patterns
- Check for similar implementations in the codebase
- Verify requirements with project documentation

---

## Common Pitfalls to Avoid

### Security Issues
- Never trust client-side data
- Always verify user permissions
- **Admin controllers**: Can return `error.message`
- **User controllers**: Return generic error messages only
- Avoid hardcoded credentials

### Performance Issues
- Avoid N+1 query problems
- Don't load unnecessary data (use `.select()`)
- Use `Promise.all()` for parallel queries
- Optimize database indexes

### Maintainability Issues
- Don't duplicate code - use utilities
- Follow consistent naming conventions
- Keep functions small and focused
- **Don't modify models without user confirmation**

---

## Conclusion

Following these guidelines ensures the Municipal Backend remains secure, maintainable, and performant. Always prioritize security and user experience while implementing new features.

**Remember:** 
- When in doubt, check `//done` routes for reference
- Always verify with user before making model changes
- Admin and User controllers have different patterns - don't mix them
