# Development & Architecture Guide

## Project Structure Overview

```
aws-final-project/
├── backend/                    # FastAPI Python application
├── frontend/                   # React Vite SPA
├── helm/dating-app/           # Kubernetes Helm chart
├── docker-compose.yml         # Local dev environment
├── README.md                  # Main documentation
├── DEPLOYMENT.md              # Deployment instructions
└── DEVELOPMENT.md             # This file
```

## Backend Architecture

### Core Components

**app/db.py** - Database Connection
- SimpleConnectionPool for connection management
- Auto-initialization of tables on startup
- Safe context manager for connections

**app/config.py** - Configuration Management
- Environment variable loading with defaults
- Settings validation
- Centralized config source

**app/auth/** - Authentication
- `utils.py`: Password hashing (bcrypt), JWT creation/validation
- `__init__.py`: Authorization dependency for FastAPI

**app/models/** - Database Models
- Pure Python classes representing database entities
- User, Profile, Photo, Like, Conversation, Message
- to_dict() methods for serialization

**app/schemas/** - Pydantic Schemas
- Request/response validation
- Type hints and documentation
- Automatic OpenAPI schema generation

**app/services/** - Business Logic
- `auth_service.py`: Registration, login
- `profile_service.py`: Profile CRUD, discovery
- `photo_service.py`: Upload, storage, deletion
- `like_service.py`: Like tracking, match detection
- `chat_service.py`: Message operations, conversations

**app/routers/** - API Endpoints
- Modular organization by feature
- Protected endpoints with `get_current_user` dependency
- Consistent error handling

### Database Design

#### users table
```sql
id (PK), email (UNIQUE), hashed_password, created_at, updated_at
```

#### profiles table
```sql
id (PK), user_id (FK UNIQUE), display_name, age, gender, 
location, bio, interests (JSONB), created_at, updated_at
```

#### photos table
```sql
id (PK), profile_id (FK), file_path, display_order, created_at
```

#### likes table
```sql
id (PK), liker_id (FK), liked_id (FK), created_at
UNIQUE(liker_id, liked_id)
```

#### conversations table
```sql
id (PK), user_id_1 (FK), user_id_2 (FK), created_at, updated_at
UNIQUE(user_id_1, user_id_2)
```

#### messages table
```sql
id (PK), conversation_id (FK), sender_id (FK), content, created_at
```

### Key Design Decisions

1. **Synchronous psycopg2** - Per requirements, enables simpler debugging
2. **Connection Pooling** - SimpleConnectionPool provides basic pooling
3. **Auto-initialization** - Tables created on startup, no separate migration step
4. **JWT Tokens** - Stateless auth, no session storage needed
5. **Local File Storage** - Disk-based for lab, easily swappable to S3
6. **Match Logic** - Dual-directional like check in database

### Adding New Features

**Example: Add "message read receipts"**

1. Add schema to `app/schemas/message.py`:
```python
class MessageResponse(BaseModel):
    # ... existing fields ...
    read_at: Optional[str] = None
```

2. Update database in `app/db.py`:
```python
cur.execute("""
    ALTER TABLE messages ADD COLUMN read_at TIMESTAMP
""")
```

3. Add method to `app/services/chat_service.py`:
```python
@staticmethod
def mark_message_read(message_id: int):
    # Implementation
```

4. Add endpoint to `app/routers/chat.py`:
```python
@router.patch("/messages/{message_id}/read")
def mark_read(message_id: int, current_user: dict = Depends(get_current_user)):
    # Implementation
```

## Frontend Architecture

### Project Structure

```
frontend/src/
├── pages/              # Full page components
│   ├── Login.jsx
│   ├── Register.jsx
│   ├── ProfileEditor.jsx
│   ├── Discover.jsx
│   ├── Matches.jsx
│   └── Chat.jsx
├── styles/            # CSS for each page
│   ├── auth.css
│   ├── profileEditor.css
│   ├── discover.css
│   ├── matches.css
│   └── chat.css
├── api.js            # Centralized API client
├── App.jsx           # Main app component
├── App.css           # Global styles
├── main.jsx          # React entry point
└── index.css         # Global CSS
```

### API Client Pattern

**src/api.js** provides:
- Axios instance with base configuration
- Request interceptor for JWT token injection
- Response interceptor for 401 handling
- Organized API methods by feature:
  - authAPI.register(), authAPI.login()
  - profileAPI.getMyProfile(), profileAPI.discoverProfiles()
  - etc.

**Usage in components:**
```javascript
import { profileAPI } from '../api'

const response = await profileAPI.getMyProfile()
const profiles = await profileAPI.discoverProfiles()
```

### State Management

**Simple localStorage approach:**
- JWT stored in localStorage, auto-attached to requests
- User ID stored for context
- Component-level state with useState for forms
- No Redux/MobX needed for MVP

**Example:**
```javascript
// After login
localStorage.setItem('token', response.data.access_token)
localStorage.setItem('user_id', response.data.user_id)

// On API calls
// Automatically added by axios interceptor
Authorization: `Bearer ${token}`

// On logout
localStorage.removeItem('token')
localStorage.removeItem('user_id')
```

### Component Patterns

**Page Component Template:**
```jsx
export default function FeaturePage() {
  const [data, setData] = useState([])
  const [isLoading, setIsLoading] = useState(false)
  const [error, setError] = useState('')

  useEffect(() => {
    loadData()
  }, [])

  const loadData = async () => {
    try {
      setIsLoading(true)
      const response = await featureAPI.getData()
      setData(response.data)
    } catch (err) {
      setError(err.response?.data?.detail || 'Error')
    } finally {
      setIsLoading(false)
    }
  }

  return (
    <div className="feature-page">
      {error && <div className="error-message">{error}</div>}
      {/* JSX */}
    </div>
  )
}
```

### Styling Approach

- CSS modules for component isolation
- Global styles in index.css and App.css
- BEM naming convention for clarity
- Mobile-responsive with flexbox/grid

### Environment Configuration

Frontend uses Vite's import.meta.env:

```javascript
// In src/api.js
const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000'
```

In `frontend/.env`:
```
VITE_API_URL=http://localhost:8000
```

## Docker Build Process

### Backend Dockerfile

```dockerfile
# Multi-stage not needed
# Single stage with Python 3.11
# System dependencies: gcc, postgresql-client
# Python dependencies: fastapi, uvicorn, etc.
# Health check via /health endpoint
# CMD: uvicorn main:app
```

### Frontend Dockerfile

```dockerfile
# Multi-stage: builder + runtime
# Stage 1: Build with Node
#   - npm install
#   - npm run build -> dist/
# Stage 2: Runtime with nginx
#   - nginx:alpine
#   - Copy dist to /usr/share/nginx/html
#   - Custom nginx.conf for SPA routing
#   - Health check via /health endpoint
```

### Nginx Configuration

Handles:
- SPA routing: try_files fallback to index.html
- Static file caching: 1-year expiry for assets
- Deny access to hidden files
- Health check endpoint

## Kubernetes Deployment

### Helm Chart Structure

**Chart.yaml** - Chart metadata

**values.yaml** - Default configuration (override for different environments)

**values-lab.yaml** - Home-lab specific values
- Single replicas
- Local storage classes
- Default passwords (change in production)

**values-aws.yaml** - AWS specific values
- Multiple replicas
- EBS storage class
- ALB ingress class
- RDS database URL

**Templates:**
- `namespace.yaml` - Creates dedicated namespace
- `configmap.yaml` - Backend and frontend config
- `secret.yaml` - PostgreSQL credentials
- `postgres.yaml` - PostgreSQL deployment + PVC + service
- `backend.yaml` - Backend deployment + service
- `frontend.yaml` - Frontend deployment + service
- `ingress.yaml` - Ingress for both services

### Deployment Flow

1. Helm reads values file
2. Templates rendered with values
3. Kubernetes resources created in order:
   - Namespace
   - ConfigMap, Secret
   - PVC
   - Postgres deployment waits for PVC
   - Backend deployment waits for postgres
   - Frontend deployment (no deps)
   - Services for each
   - Ingress routes traffic

### Network Architecture

```
Internet
    |
  Ingress (nginx/traefik)
    |
    +-> Frontend Service (80) -> Frontend Pods
    |
    +-> Backend Service (8000) -> Backend Pods
                                       |
                                    Postgres Service (5432)
                                       |
                                    Postgres Pod
```

### Storage

**PVC for Postgres:**
- ReadWriteOnce access mode
- Survives pod restarts
- Data persists across deployments

**PVC for Backend Media:**
- ReadWriteMany access mode (for multiple replicas)
- Shared media storage across pods
- Migrates to S3 for cloud deployments

## Development Workflow

### Local Testing

```bash
# 1. Modify code
# 2. Test with compose
docker-compose up -d
curl http://localhost:8000/docs

# 3. Modify Helm values
# 4. Test with Helm (dry-run)
helm install dating-app ./helm/dating-app \
  -n dating-app --dry-run --debug

# 5. Test with Helm (actual)
helm install dating-app ./helm/dating-app \
  -n dating-app --create-namespace

# 6. Verify
kubectl get all -n dating-app
```

### Code Changes

**Backend changes:**
- Edit Python files in app/
- Changes automatically available in dev environment
- Production requires rebuilding Docker image

**Frontend changes:**
- Edit .jsx files
- Changes automatically available in dev environment
- Production requires rebuilding and redeploying

**Database schema changes:**
- Modify app/db.py init_db()
- For Alembic (future): `alembic revision --autogenerate`
- Existing migrations: Update manually or recreate database

## Performance Considerations

### Backend

- Connection pooling limits: Currently 1-20 connections
- Query optimization: Use indexes on foreign keys
- Response caching: Can add for discover endpoint
- Pagination: Not implemented yet, add for large datasets

### Frontend

- Image optimization: Profile pictures should be compressed
- Lazy loading: Add for discover card images
- Code splitting: Can split by route
- Caching: Service workers for offline support

### Database

- Indexes created on common query columns
- JSONB for interests enables efficient queries
- Unique constraints prevent duplicates
- Foreign keys maintain referential integrity

## Testing Strategy

### Unit Tests (Future)
```python
# backend/tests/
# test_auth.py - Auth functions
# test_services.py - Service logic
# test_routers.py - API endpoints
```

### Integration Tests (Future)
```python
# Full workflow testing
# Database interactions
# API contract validation
```

### E2E Tests (Future)
```javascript
# frontend/tests/
# User registration flow
# Profile creation
# Swiping and matching
# Chat functionality
```

### Manual Testing Checklist

- [ ] Registration with new email
- [ ] Login with correct password
- [ ] Create and update profile
- [ ] Upload multiple photos
- [ ] Delete photos
- [ ] View discover profiles
- [ ] Like a user
- [ ] Check matches
- [ ] Send message to match
- [ ] View conversation history
- [ ] Logout

## Security Considerations

### Current Implementation
- ✅ Password hashing with bcrypt
- ✅ JWT with expiration
- ✅ CORS configured
- ✅ Protected endpoints
- ✅ SQL injection prevention (parameterized queries)

### Recommended Additions
- [ ] Rate limiting on auth endpoints
- [ ] HTTPS/TLS enforcement
- [ ] CSRF token for state-changing operations
- [ ] Input validation and sanitization
- [ ] Audit logging
- [ ] API key authentication for service-to-service
- [ ] Secrets management (Vault)
- [ ] Regular security scanning
- [ ] Penetration testing

### Data Protection
- [ ] Encrypt sensitive data in transit (HTTPS)
- [ ] Encrypt sensitive data at rest
- [ ] Implement data retention policies
- [ ] GDPR compliance (right to delete, data export)
- [ ] Regular backups with encryption
- [ ] Secure backup storage

## Common Issues & Solutions

### Issue: Photo uploads fail
**Cause:** Media directory not writable
**Solution:** Check MEDIA_DIR permissions, ensure PVC mounted

### Issue: Matches not showing
**Cause:** Mutual like check query fails
**Solution:** Verify both users liked each other, check database

### Issue: Slow profile discovery
**Cause:** N+1 query problem
**Solution:** Add query optimization, batch load photos

### Issue: Connection pool exhausted
**Cause:** Too many concurrent requests
**Solution:** Increase pool size, add connection timeout

## Future Enhancements

1. **WebSocket Chat**
   - Real-time messages without polling
   - Typing indicators
   - Read receipts

2. **Image Optimization**
   - Automatic compression
   - Multiple sizes for responsive design
   - CDN distribution

3. **Recommendation Engine**
   - Machine learning for match suggestions
   - Interest-based filtering
   - Location-based matching

4. **Advanced Features**
   - Video calls
   - Story features
   - Search and filtering
   - Blocking/reporting
   - Verification badges

5. **Infrastructure**
   - Load balancing improvements
   - Caching layer (Redis)
   - Message queue (RabbitMQ) for async tasks
   - Monitoring and alerting
   - CI/CD pipeline
   - Database read replicas
