# Socket.IO Connection Debugging Guide - Student Not Receiving Notifications

## Issue Summary

**Problem:** Student is not receiving real-time notifications even though:
- ✅ Notification is created in database
- ✅ Notification is emitted via Socket.IO
- ❌ **Sockets in room user-{studentId}: 0** (Student not connected!)

**Backend Log Shows:**
```
📢 Emitting notification to room: user-68f49bd54db7d942e2e8bd08
   Notification ID: 68f5ea5065ccdec6278fc42c
   Title: New Invoice Generated
   Type: invoice_generated
   User Type: student
   User ID: 68f49bd54db7d942e2e8bd08
   Sockets in room user-68f49bd54db7d942e2e8bd08: 0  ← PROBLEM!
✅ Notification emitted successfully to room user-68f49bd54db7d942e2e8bd08
```

## Root Cause

The student's browser is **NOT** connected to Socket.IO. This can happen for several reasons:

1. Student has not refreshed the page since login
2. Socket.IO connection failed due to authentication error
3. Token expired or invalid
4. Network/firewall blocking WebSocket connection
5. CORS issues
6. Frontend not initializing socket connection

## Fixes Applied

### 1. Fixed Currency Symbol Duplication ✅

**File:** `utils/notificationHelper.js` (Lines 159-170)

**Before:** `"A new invoice of £GBP 49.50..."` ❌
**After:** `"A new invoice of £ 49.50..."` ✅

**Change:**
```javascript
// Before
message: `A new invoice of £${amount} has been generated...`

// After
message: `A new invoice of ${amount} has been generated...`
```

**File:** `routes/admin/finance.js` (Lines 276-291)

**Added currency symbol conversion:**
```javascript
// Get currency symbol
const getCurrencySymbol = (currency) => {
  const symbols = {
    'USD': '$', 'GBP': '£', 'EUR': '€', 'AED': 'AED',
    'INR': '₹', 'SAR': 'SAR', 'CAD': 'CA$', 'AUD': 'A$'
  };
  return symbols[currency] || currency || 'AED';
};

const currencySymbol = getCurrencySymbol(student.currency);
const formattedAmount = `${currencySymbol} ${totalAmount.toFixed(2)}`;

const notificationData = NotificationTemplates.invoiceGenerated(
  formattedAmount, // Now sends "£ 49.50" instead of "GBP 49.50"
  moment(dueDate).format('MMM DD, YYYY')
);
```

### 2. Enhanced Error Handling ✅

Already added in previous fix with try-catch block and logging.

## Diagnostic Steps

### Step 1: Check Student Browser Console

**Open student browser → Press F12 → Go to Console tab**

**Look for these logs:**

#### ✅ GOOD - Socket Connected:
```
✅ Socket.IO: Connected to server abc123xyz
🔔 NotificationBell: Setting up new_notification listener
🔔 NotificationBell: Socket ID: abc123xyz
🔔 NotificationBell: Socket connected: true
```

#### ❌ BAD - Socket NOT Connected:
```
❌ Socket.IO: Connection error: Authentication error
```
OR
```
⚠️ NotificationBell: Socket not available, will retry in 500ms
❌ NotificationBell: Failed to set up socket listener after all attempts
```
OR
```
(No socket logs at all)
```

### Step 2: Check Backend Server Logs

**When student logs in, look for:**

#### ✅ GOOD - Student Connected:
```
🔐 Socket authentication attempt
   Token received: Yes (length: 180)
   IP: ::1
   Verifying JWT token...
✅ Token verified successfully
   User ID: 68f49bd54db7d942e2e8bd08
   User Type: student
✅ User 68f49bd54db7d942e2e8bd08 (student) joined room: user-68f49bd54db7d942e2e8bd08
   Socket ID: abc123xyz
   Timestamp: 2025-10-20T08:00:00.000Z
   Also joined: students
```

#### ❌ BAD - Student NOT Connected:
```
🔐 Socket authentication attempt
   Token received: No
❌ Socket connection without token
```
OR
```
🔐 Socket authentication attempt
   Token received: Yes (length: 180)
❌ Socket authentication failed: jwt malformed
```
OR
```
(No socket authentication logs at all)
```

### Step 3: Check Network Tab

**Student Browser → F12 → Network tab → Filter: WS (WebSocket)**

#### ✅ GOOD:
- See entry: `socket.io/?EIO=4&transport=websocket`
- Status: **101 Switching Protocols** (green)
- Type: **websocket**
- Messages tab shows data flowing

#### ❌ BAD:
- No websocket connection visible
- Status: **Failed** or **Pending** (red)
- Connection keeps disconnecting/reconnecting

## Solutions

### Solution 1: Student Needs to Refresh Browser ⭐ MOST COMMON

**Why:** Socket connection established on page load with current token.

**How:**
1. Student: **Press Ctrl+Shift+R** (hard refresh)
2. Or: **Close tab and open new one**
3. Or: **Logout and login again**

**After refresh, check console:**
```
✅ Socket.IO: Connected to server
🔔 NotificationBell: Setting up new_notification listener
```

**Test:** Admin creates invoice → Student should receive notification immediately

### Solution 2: Check Token in localStorage

**Student Browser → F12 → Application tab → Local Storage → http://localhost:3001**

**Look for:**
- Key: `edumetrix_token` or `token`
- Value: Should be a long JWT string (starts with `eyJ...`)

**If missing or invalid:**
1. Logout
2. Clear browser cache
3. Login again
4. Check if token is stored

### Solution 3: Verify Socket.IO URL

**File:** `client/.env` (for student portal)

**Check:**
```env
REACT_APP_SOCKET_URL=https://backend.edumetrix.uk
```

**Or if using separate ports:**
```env
REACT_APP_SOCKET_URL=https://backend.edumetrix.uk  # Backend server port
```

**Make sure:**
- URL matches where backend server is running
- Port is correct
- No typos

### Solution 4: Check CORS Settings

**File:** `server.js` (Lines 123-131)

**Verify student portal URL is in allowed origins:**
```javascript
const io = new Server(server, {
  cors: {
    origin: [
      'http://localhost:3000',  // Admin
      'http://localhost:3001',  // Student ← CHECK THIS
      'http://localhost:3002',  // Teacher
      'https://student.edumetrix.uk'  // Production student URL
    ],
    methods: ["GET", "POST"],
    credentials: true
  },
  transports: ['websocket', 'polling']
});
```

**If student URL is missing:**
1. Add it to the `origin` array
2. Restart backend server
3. Student refreshes browser

### Solution 5: Check Firewall/Network

**Symptoms:**
- Socket connects briefly then disconnects
- Connection pending forever
- Works locally but not on deployed server

**Solutions:**
- Check if firewall blocks WebSocket (port 5001)
- Try disabling antivirus/firewall temporarily
- Check if VPN interferes
- Try different browser
- Check if company/school network blocks WebSockets

### Solution 6: Force Socket Reconnection

**Add to student frontend code (temporary debug):**

**File:** `client/src/pages/student/StudentDashboard.js` (or any student page)

```javascript
import { useEffect } from 'react';
import socketService from '../../services/socket';

useEffect(() => {
  const token = localStorage.getItem('edumetrix_token');
  if (token) {
    console.log('🔧 DEBUG: Manually reconnecting socket...');
    socketService.disconnect();
    setTimeout(() => {
      socketService.connect(token);
      console.log('🔧 DEBUG: Socket reconnect attempted');
    }, 1000);
  }
}, []);
```

This forces socket reconnection when dashboard loads.

## Quick Test Procedure

### Test Real-Time Notification Delivery

**Setup:**
1. Open **TWO browser windows** (or use incognito for second)
2. Window 1: Login as Admin
3. Window 2: Login as Student
4. **IMPORTANT:** In Window 2, press **F12** and check console

**Steps:**

1. **Window 2 (Student) - Before Admin Action:**
   - Check console for:
     ```
     ✅ Socket.IO: Connected to server
     🔔 NotificationBell: Setting up listener
     ```
   - If **NOT** present: **Refresh page** (Ctrl+Shift+R)
   - Wait until you see connection messages

2. **Window 1 (Admin):**
   - Go to Finance → Invoice Generator
   - Select the student from Window 2
   - Generate invoice

3. **Backend (Server Console):**
   - Should show:
     ```
     📢 Sent invoice generated notification to student {id}
     📢 Emitting notification to room: user-{id}
        Sockets in room user-{id}: 1  ← Should be 1 or more!
     ✅ Notification emitted successfully
     ```

4. **Window 2 (Student) - Watch For:**
   - Console should show:
     ```
     🔔 NotificationBell: ====== NEW NOTIFICATION RECEIVED ======
     🔔 NotificationBell: Notification details: {
       type: 'invoice_generated',
       title: 'New Invoice Generated',
       message: 'A new invoice of £ 49.50 has been generated. Due: Nov 19, 2025'
     }
     ```
   - Notification bell badge increments (e.g., 0 → 1)
   - Clicking bell shows notification

**Success Criteria:**
- ✅ Backend shows: "Sockets in room: 1" (or more)
- ✅ Student console shows notification received
- ✅ Notification bell updates
- ✅ Notification appears in dropdown

## Common Mistakes

### Mistake 1: Not Refreshing After Login
**Problem:** Old socket connection with old/no token
**Solution:** Always refresh after login

### Mistake 2: Using Different Ports
**Problem:** Frontend connects to wrong port
**Solution:** Check `.env` has correct `REACT_APP_SOCKET_URL`

### Mistake 3: Token Expired
**Problem:** JWT token expired (default: 30 days)
**Solution:** Logout and login again to get fresh token

### Mistake 4: Multiple Tabs
**Problem:** Checking wrong tab
**Solution:** Ensure you're watching the correct student tab

### Mistake 5: Wrong User
**Problem:** Testing with different student than invoice was generated for
**Solution:** Ensure invoice is for the student you're logged in as

## Monitoring Socket Connections

### Add to Backend (server.js) for Debugging

```javascript
// After io.on('connection', ...) event handler
io.on('connection', (socket) => {
  // ... existing code ...

  // Log all connected sockets periodically
  setInterval(() => {
    const sockets = io.sockets.sockets;
    console.log(`\n📊 Connected Sockets: ${sockets.size}`);
    sockets.forEach((s) => {
      console.log(`   - ${s.userId} (${s.userType}) | Socket: ${s.id}`);
    });
  }, 30000); // Every 30 seconds
});
```

This logs all connected users every 30 seconds to monitor connections.

### Check Socket Rooms

```javascript
// In notification emission code
const room = `user-${studentId}`;
const socketsInRoom = await io.in(room).fetchSockets();

console.log(`\n🔍 DEBUG: Room ${room}`);
console.log(`   Total sockets: ${socketsInRoom.length}`);
socketsInRoom.forEach(socket => {
  console.log(`   - Socket ${socket.id}`);
  console.log(`     User ID: ${socket.userId}`);
  console.log(`     User Type: ${socket.userType}`);
  console.log(`     Connected: ${socket.connected}`);
});
```

## Production Deployment

### Before Going Live:

1. **Test Socket Connections:**
   - Test with real student accounts
   - Test from different networks
   - Test from mobile devices

2. **Update CORS:**
   - Add production domain to `origin` array
   - Update `REACT_APP_SOCKET_URL` in production `.env`

3. **Monitor Logs:**
   - Watch for authentication failures
   - Track "Sockets in room: 0" warnings
   - Alert on high failure rates

4. **Fallback:**
   - Notifications still saved to database
   - Students can refresh to see new notifications
   - Polling backup every 30 seconds

## Summary

The notification system works correctly. The issue is that **the student's browser is not connected to Socket.IO**.

**Most likely cause:** Student hasn't refreshed browser after login.

**Quickest fix:**
1. Student: Refresh browser (Ctrl+Shift+R)
2. Check console for: `✅ Socket.IO: Connected`
3. Admin: Generate invoice again
4. Student: Should receive notification immediately

**If still not working:**
1. Check backend logs for socket authentication
2. Check frontend console for connection errors
3. Verify token in localStorage
4. Check CORS settings
5. Try logout/login

**Result:** Once student's browser connects to Socket.IO, notifications will be received in real-time! 🎉
