# Week 8: Test Scheduling & Notifications System

Complete implementation of test scheduling with multi-channel notifications (Push + Email) and queue-based delivery system.

## 📋 Table of Contents
- [Features Implemented](#features-implemented)
- [Architecture Overview](#architecture-overview)
- [Installation & Setup](#installation--setup)
- [API Endpoints](#api-endpoints)
- [Configuration](#configuration)
- [Queue Workers](#queue-workers)
- [Testing](#testing)
- [Troubleshooting](#troubleshooting)

---

## ✨ Features Implemented

### Day 1-2: Test Scheduling Notifications ✅
- **NotificationService** for centralized notification management
- **Automatic scheduling** of 4 types of notifications:
  1. Immediate notification when test is scheduled
  2. 24-hour reminder before test
  3. 1-hour reminder before test
  4. "Test is Live" notification at start time
- **Multi-channel delivery**:
  - Push notifications via Firebase FCM ✅
  - Email notifications via Laravel Mail ✅
  - Database notifications for in-app display ✅
- **Deep linking** to test pages in mobile app

### Day 3: Email Notification System ✅
- **4 Beautiful HTML email templates**:
  - Test Scheduled (gradient purple header)
  - Test Reminder (blue/urgent red gradients)
  - Test Live (green animated gradient)
  - Results Published (pink gradient)
- **Professional features**:
  - Inline CSS for email client compatibility
  - Responsive design for mobile
  - Call-to-action buttons
  - Test details and countdown timers
  - Both HTML and plain text support

### Day 4: Queue System ✅
- **Database queue driver** configured
- **All notifications queued** (non-blocking API responses)
- **Automatic retry** mechanism (3 attempts with exponential backoff)
- **Failed job handling** with admin monitoring
- **Job batching** support for bulk notifications

### Day 5: Schedule Management API ✅
- **Update schedule** endpoint with validation
- **Cancel test** endpoint with student notifications
- **Get scheduled tests** with filtering and statistics
- **Automatic notification rescheduling** when test is updated
- **Prevents modification** if students have attempted

---

## 🏗️ Architecture Overview

```
┌─────────────────────────────────────────────────────────────┐
│                    Test Scheduling Flow                      │
└─────────────────────────────────────────────────────────────┘

1. Teacher creates test with schedule
   ↓
2. TestSeriesController saves test
   ↓
3. TestNotificationService creates notification schedule
   ↓
4. ScheduledNotification records created in DB
   ↓
5. SendTestNotification jobs queued with delays
   ↓
6. Queue workers process jobs at scheduled times
   ↓
7. Notifications sent via:
   - Database (in-app)
   - Email (SMTP)
   - FCM Push (Firebase)
```

### Database Schema

**testseries table (new fields)**:
- `scheduled_at` - Test start timestamp
- `duration_minutes` - Test duration
- `auto_publish_results` - Auto-publish flag
- `is_cancelled` - Cancellation flag
- `cancelled_at` - Cancellation timestamp
- `cancelled_by` - Teacher who cancelled

**scheduled_notifications table (new)**:
- `test_series_id` - Foreign key to testseries
- `notification_type` - Type: test_scheduled, 24h_reminder, 1h_reminder, test_live
- `scheduled_for` - When to send
- `is_sent` - Delivery status
- `sent_at` - Actual send time
- `job_id` - Queue job reference
- `is_cancelled` - Cancellation flag

**jobs table (Laravel queue)**:
- `queue` - Queue name
- `payload` - Job data
- `attempts` - Retry count
- `available_at` - When job should run

---

## 🚀 Installation & Setup

### 1. Run Migrations

```bash
php artisan migrate
```

This will create:
- `jobs` table
- `failed_jobs` table
- `job_batches` table
- `scheduled_notifications` table
- Add scheduling fields to `testseries` table

### 2. Configure Environment

Add to `.env`:

```env
# Queue Configuration
QUEUE_CONNECTION=database

# Mail Configuration (for email notifications)
MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=your-email@gmail.com
MAIL_PASSWORD=your-app-specific-password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=support@pathshalaa.in
MAIL_FROM_NAME="Pathshalaa"

# Firebase Configuration (already configured)
FIREBASE_CREDENTIALS=storage/app/firebase/service-account.json

# App URL (for email links)
APP_URL=https://pathshalaa.in
```

### 3. Start Queue Workers

**Development:**
```bash
php artisan queue:work --tries=3 --timeout=300
```

**Production (with Supervisor):**

Create `/etc/supervisor/conf.d/pathshalaa-worker.conf`:

```ini
[program:pathshalaa-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /home/user/pathshalaa_api/artisan queue:work database --sleep=3 --tries=3 --max-time=3600 --timeout=300
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=www-data
numprocs=2
redirect_stderr=true
stdout_logfile=/home/user/pathshalaa_api/storage/logs/worker.log
stopwaitsecs=3600
```

Then:
```bash
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start pathshalaa-worker:*
```

### 4. Add Routes

Add to `routes/api.php`:

```php
// Teacher routes - Test Scheduling
Route::middleware(['auth:sanctum', 'role:teacher'])->prefix('v2/tutor')->group(function () {
    // Schedule management
    Route::put('test-series/{id}/schedule', [TestSeriesController::class, 'updateSchedule']);
    Route::post('test-series/{id}/cancel', [TestSeriesController::class, 'cancelTest']);
    Route::get('test-series/scheduled', [TestSeriesController::class, 'getScheduledTests']);
});

// Admin routes - Queue Monitoring
Route::middleware(['auth:sanctum', 'role:admin'])->prefix('v2/admin/queue')->group(function () {
    Route::get('stats', [QueueMonitoringController::class, 'getQueueStats']);
    Route::get('failed-jobs', [QueueMonitoringController::class, 'getFailedJobs']);
    Route::post('failed-jobs/{id}/retry', [QueueMonitoringController::class, 'retryFailedJob']);
    Route::delete('failed-jobs/{id}', [QueueMonitoringController::class, 'deleteFailedJob']);
    Route::delete('failed-jobs', [QueueMonitoringController::class, 'clearFailedJobs']);
    Route::get('scheduled-notifications', [QueueMonitoringController::class, 'getScheduledNotifications']);
});
```

---

## 📡 API Endpoints

### 1. Create Test with Schedule

**POST** `/api/v2/tutor/test-series/auto-generate`

```json
{
  "test_series_name": "Mathematics Final Test",
  "class_id": 1,
  "subject_ids": [10],
  "topic_ids": [101, 102],
  "question_count": 50,
  "per_question_marks": 1,
  "total_time": 60,
  "use_ai_generation": true,
  "consent_given": true,
  "scheduled_at": "2025-01-15 10:00:00",
  "auto_publish_results": true
}
```

**Response:**
```json
{
  "status": true,
  "message": "Test series created successfully and notifications scheduled",
  "data": {
    "test_series_id": 123,
    "test_series_name": "Mathematics Final Test",
    "total_questions": 50,
    "from_database": 30,
    "from_ai": 20,
    "coins_used": 100,
    "remaining_balance": 400,
    "scheduled_at": "2025-01-15 10:00:00",
    "notifications_scheduled": true
  }
}
```

### 2. Update Test Schedule

**PUT** `/api/v2/tutor/test-series/{id}/schedule`

```json
{
  "scheduled_at": "2025-01-16 14:00:00",
  "duration_minutes": 90,
  "auto_publish_results": true
}
```

**Response:**
```json
{
  "status": true,
  "message": "Test rescheduled successfully and students notified",
  "data": {
    "id": 123,
    "name": "Mathematics Final Test",
    "scheduled_at": "2025-01-16 14:00:00",
    "duration_minutes": 90,
    "auto_publish_results": true
  }
}
```

### 3. Cancel Test

**POST** `/api/v2/tutor/test-series/{id}/cancel`

**Response:**
```json
{
  "status": true,
  "message": "Test cancelled successfully and students notified",
  "data": {
    "id": 123,
    "name": "Mathematics Final Test",
    "is_cancelled": true,
    "cancelled_at": "2025-01-14 15:30:00"
  }
}
```

### 4. Get Scheduled Tests

**GET** `/api/v2/tutor/test-series/scheduled?from_date=2025-01-01&to_date=2025-01-31`

**Response:**
```json
{
  "status": true,
  "message": "Scheduled tests retrieved successfully",
  "data": {
    "tests": [
      {
        "id": 123,
        "name": "Mathematics Final Test",
        "scheduled_at": "2025-01-15 10:00:00",
        "scheduled_date": "15 Jan 2025",
        "scheduled_time": "10:00 AM",
        "duration_minutes": 60,
        "total_questions": 50,
        "per_question_marks": 1,
        "auto_publish_results": true,
        "is_cancelled": false,
        "enrolled_students": 45,
        "pending_notifications": 3,
        "status": "upcoming",
        "time_until_test": "in 2 days"
      }
    ],
    "total_count": 1,
    "upcoming_count": 1,
    "completed_count": 0,
    "cancelled_count": 0
  }
}
```

### 5. Queue Monitoring (Admin)

**GET** `/api/v2/admin/queue/stats`

**Response:**
```json
{
  "status": true,
  "message": "Queue statistics retrieved successfully",
  "data": {
    "jobs": {
      "pending": 15,
      "failed_total": 3,
      "failed_recent_24h": 1
    },
    "scheduled_notifications": {
      "total": 120,
      "sent": 85,
      "cancelled": 10,
      "pending": 25,
      "upcoming_24h": 8
    },
    "queues_by_connection": [
      {"queue": "default", "count": 15}
    ],
    "timestamp": "2025-01-14 15:45:00"
  }
}
```

**GET** `/api/v2/admin/queue/failed-jobs`

Lists all failed jobs with pagination.

**POST** `/api/v2/admin/queue/failed-jobs/{id}/retry`

Retry a specific failed job.

**DELETE** `/api/v2/admin/queue/failed-jobs/{id}`

Delete a specific failed job.

**DELETE** `/api/v2/admin/queue/failed-jobs`

Clear all failed jobs.

---

## ⚙️ Configuration

### Email Templates Customization

Templates are located in `resources/views/emails/`:
- `test-scheduled.blade.php`
- `test-reminder.blade.php`
- `test-live.blade.php`
- `test-results-published.blade.php`

Customize colors, fonts, and content as needed. All templates include inline CSS for maximum email client compatibility.

### Notification Messages

Edit messages in `app/Services/TestNotificationService.php`:

```php
public function getNotificationMessage(TestSeries $testSeries, string $type): string
{
    // Customize messages here
}
```

### Queue Configuration

Adjust retry attempts and timeout in `app/Jobs/SendTestNotification.php`:

```php
public $timeout = 300; // 5 minutes
public $tries = 3; // Retry 3 times
public $backoff = [60, 120, 300]; // Backoff intervals
```

---

## 🧪 Testing

### Test Email Sending

```bash
php artisan tinker
```

```php
use App\Models\TestSeries;
use App\Models\User;
use App\Mail\TestScheduledMail;
use Illuminate\Support\Facades\Mail;

$test = TestSeries::find(1);
$student = User::find(2);

Mail::to($student->email)->send(new TestScheduledMail($test, $student));
```

### Test Queue Processing

```bash
# Process one job
php artisan queue:work --once

# Process jobs with verbose output
php artisan queue:work --verbose

# List failed jobs
php artisan queue:failed

# Retry all failed jobs
php artisan queue:retry all
```

### Test Notifications

1. Create a test with schedule in the future
2. Check `scheduled_notifications` table
3. Check `jobs` table for queued jobs
4. Run queue worker
5. Verify notifications sent

---

## 🐛 Troubleshooting

### Notifications Not Sending

1. **Check queue worker is running:**
   ```bash
   ps aux | grep "queue:work"
   ```

2. **Check failed jobs:**
   ```bash
   php artisan queue:failed
   ```

3. **Check logs:**
   ```bash
   tail -f storage/logs/laravel.log
   ```

### Email Not Delivered

1. **Verify SMTP settings in `.env`**
2. **Check email credentials**
3. **Test SMTP connection:**
   ```bash
   php artisan tinker
   Mail::raw('Test email', function($msg) {
       $msg->to('test@example.com')->subject('Test');
   });
   ```

### FCM Push Not Working

1. **Verify Firebase credentials exist:**
   ```bash
   ls -la storage/app/firebase/service-account.json
   ```

2. **Check device tokens in users table**
3. **Review FCM error logs**

### Queue Jobs Stuck

1. **Clear failed jobs:**
   ```bash
   php artisan queue:flush
   ```

2. **Restart queue workers:**
   ```bash
   sudo supervisorctl restart pathshalaa-worker:*
   ```

3. **Check database connection**

---

## 📊 Monitoring Best Practices

1. **Set up cron for queue monitoring:**
   ```bash
   * * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
   ```

2. **Use Supervisor for production** (see configuration above)

3. **Monitor queue stats regularly** via admin API

4. **Set up alerts for failed jobs** (optional: integrate with Slack/Email)

5. **Review logs daily:**
   ```bash
   tail -f storage/logs/worker.log
   ```

---

## 📝 Summary

### Files Created:
- ✅ Migrations (5 files)
- ✅ Models: ScheduledNotification
- ✅ Services: TestNotificationService
- ✅ Jobs: SendTestNotification
- ✅ Mailables: 4 email classes
- ✅ Blade Templates: 4 email templates
- ✅ Controllers: Updated TestSeriesController, QueueMonitoringController
- ✅ Documentation: This file

### Database Tables:
- ✅ jobs
- ✅ failed_jobs
- ✅ job_batches
- ✅ scheduled_notifications
- ✅ testseries (updated)

### API Endpoints:
- ✅ 3 Teacher endpoints (schedule, cancel, list)
- ✅ 6 Admin endpoints (monitoring)

### Notification Channels:
- ✅ Push (FCM)
- ✅ Email (SMTP)
- ✅ Database (In-app)

---

## 🎉 Success Criteria

- [x] Tests can be scheduled during creation
- [x] Automatic notifications trigger at correct times
- [x] Multi-channel delivery (Push + Email + Database)
- [x] Beautiful HTML email templates
- [x] Queue-based non-blocking system
- [x] Retry mechanism for failures
- [x] Schedule management API
- [x] Admin monitoring dashboard
- [x] Production-ready with Supervisor

**Week 8 Implementation: COMPLETE ✅**
