# WebSocket Subscription Guide

## 📋 Overview

This guide explains how WebSocket subscriptions work in the Jackbox Game Picker and which events require subscriptions.

## 🔌 Connection & Authentication

### 1. Connect to WebSocket

```javascript
const ws = new WebSocket('ws://localhost:5000/api/sessions/live');
```

### 2. Authenticate

```javascript
ws.send(JSON.stringify({
  type: 'auth',
  token: 'YOUR_JWT_TOKEN'
}));
```

### 3. Wait for Auth Success

```javascript
ws.on('message', (data) => {
  const msg = JSON.parse(data.toString());
  if (msg.type === 'auth_success') {
    console.log('Authenticated!');
    // Now you can subscribe to sessions
  }
});
```

## 📨 Event Types & Subscription Requirements

| Event Type | Requires Subscription? | Broadcast To | When to Subscribe |
|------------|------------------------|--------------|-------------------|
| `session.started` | ❌ **NO** | All authenticated clients | N/A - Automatic |
| `game.added` | ✅ **YES** | Subscribed clients only | After session.started |
| `vote.received` | ✅ **YES** | Subscribed clients only | After session.started |
| `session.ended` | ✅ **YES** | Subscribed clients only | After session.started |

## 🎯 Subscription Strategy

### Strategy 1: Auto-Subscribe to New Sessions (Recommended for Bots)

```javascript
ws.on('message', (data) => {
  const msg = JSON.parse(data.toString());
  
  // After authentication
  if (msg.type === 'auth_success') {
    console.log('✅ Authenticated');
  }
  
  // Auto-subscribe to new sessions
  if (msg.type === 'session.started') {
    const sessionId = msg.data.session.id;
    console.log(`🎮 New session ${sessionId} started!`);
    
    // Subscribe to this session
    ws.send(JSON.stringify({
      type: 'subscribe',
      sessionId: sessionId
    }));
  }
  
  // Now you'll receive game.added, vote.received, and session.ended
  if (msg.type === 'game.added') {
    console.log(`🎲 Game: ${msg.data.game.title}`);
  }
  
  if (msg.type === 'session.ended') {
    console.log(`🌙 Session ended! ${msg.data.session.games_played} games played`);
  }
});
```

### Strategy 2: Subscribe to Active Session on Connect

```javascript
ws.on('message', (data) => {
  const msg = JSON.parse(data.toString());
  
  if (msg.type === 'auth_success') {
    console.log('✅ Authenticated');
    
    // Fetch active session from API
    fetch('http://localhost:5000/api/sessions/active')
      .then(res => res.json())
      .then(session => {
        if (session && session.id) {
          // Subscribe to active session
          ws.send(JSON.stringify({
            type: 'subscribe',
            sessionId: session.id
          }));
        }
      });
  }
});
```

### Strategy 3: Subscribe to Specific Session

```javascript
ws.on('message', (data) => {
  const msg = JSON.parse(data.toString());
  
  if (msg.type === 'auth_success') {
    console.log('✅ Authenticated');
    
    // Subscribe to specific session
    const sessionId = 17;
    ws.send(JSON.stringify({
      type: 'subscribe',
      sessionId: sessionId
    }));
  }
  
  if (msg.type === 'subscribed') {
    console.log(`✅ Subscribed to session ${msg.sessionId}`);
  }
});
```

## 🔄 Complete Bot Flow

```javascript
const WebSocket = require('ws');

class JackboxBot {
  constructor(token) {
    this.token = token;
    this.ws = null;
    this.currentSessionId = null;
  }
  
  connect() {
    this.ws = new WebSocket('ws://localhost:5000/api/sessions/live');
    
    this.ws.on('open', () => {
      console.log('🔌 Connected to WebSocket');
      this.authenticate();
    });
    
    this.ws.on('message', (data) => {
      this.handleMessage(JSON.parse(data.toString()));
    });
  }
  
  authenticate() {
    this.ws.send(JSON.stringify({
      type: 'auth',
      token: this.token
    }));
  }
  
  handleMessage(msg) {
    switch (msg.type) {
      case 'auth_success':
        console.log('✅ Authenticated');
        // Don't subscribe yet - wait for session.started
        break;
        
      case 'session.started':
        this.currentSessionId = msg.data.session.id;
        console.log(`🎮 Session ${this.currentSessionId} started!`);
        
        // Auto-subscribe to this session
        this.ws.send(JSON.stringify({
          type: 'subscribe',
          sessionId: this.currentSessionId
        }));
        
        // Announce to users
        this.announce(`Game Night has started! Session #${this.currentSessionId}`);
        break;
        
      case 'subscribed':
        console.log(`✅ Subscribed to session ${msg.sessionId}`);
        break;
        
      case 'game.added':
        console.log(`🎲 Game: ${msg.data.game.title}`);
        this.announce(`Now playing: ${msg.data.game.title}`);
        break;
        
      case 'vote.received':
        console.log(`🗳️ Vote: ${msg.data.vote.type}`);
        break;
        
      case 'session.ended':
        console.log(`🌙 Session ${msg.data.session.id} ended`);
        this.announce(`Game Night ended! ${msg.data.session.games_played} games played`);
        this.currentSessionId = null;
        break;
    }
  }
  
  announce(message) {
    // Send to IRC/Discord/Kosmi/etc
    console.log(`📢 ${message}`);
  }
}

// Usage
const bot = new JackboxBot('YOUR_JWT_TOKEN');
bot.connect();
```

## 📊 Subscription Lifecycle

```
1. Connect to WebSocket
   ↓
2. Send auth message
   ↓
3. Receive auth_success
   ↓
4. Wait for session.started (no subscription needed)
   ↓
5. Receive session.started
   ↓
6. Send subscribe message with sessionId
   ↓
7. Receive subscribed confirmation
   ↓
8. Now receive: game.added, vote.received, session.ended
   ↓
9. Receive session.ended
   ↓
10. Wait for next session.started (repeat from step 4)
```

## 🔍 Debugging

### Check What You're Subscribed To

The WebSocket manager tracks subscriptions. Check backend logs:

```
[WebSocket] Client subscribed to session 17
[WebSocket] Client unsubscribed from session 17
```

### Verify Event Reception

**session.started** - Should receive immediately after authentication (no subscription needed):
```
[WebSocket] Broadcasted session.started to 2 authenticated client(s)
```

**game.added, vote.received, session.ended** - Only after subscribing:
```
[WebSocket] Broadcasted game.added to 1 client(s) for session 17
```

### Common Issues

1. **Not receiving session.started:**
   - ✅ Are you authenticated?
   - ✅ Is your WebSocket connection open?
   - ✅ Check backend logs for broadcast confirmation

2. **Not receiving game.added:**
   - ✅ Did you subscribe to the session?
   - ✅ Did you receive `subscribed` confirmation?
   - ✅ Is the session ID correct?

3. **Not receiving session.ended:**
   - ✅ Are you still subscribed to the session?
   - ✅ Did the session actually close?
   - ✅ Check backend logs

## 🎯 Best Practices

1. **Auto-subscribe to new sessions** when you receive `session.started`
2. **Don't subscribe before session.started** - there's nothing to subscribe to yet
3. **Handle reconnections** - re-authenticate and re-subscribe on reconnect
4. **Use polling as fallback** - poll `/api/sessions/active` every 30s as backup
5. **Unsubscribe when done** - clean up subscriptions when you're done with a session
6. **Validate session IDs** - make sure the session exists before subscribing

## 📝 Summary

### ❌ No Subscription Required
- `session.started` - Broadcast to **all authenticated clients**

### ✅ Subscription Required
- `game.added` - Only to **subscribed clients**
- `vote.received` - Only to **subscribed clients**
- `session.ended` - Only to **subscribed clients**

### 🎯 Recommended Flow
1. Authenticate
2. Wait for `session.started` (automatic)
3. Subscribe to the session
4. Receive `game.added`, `vote.received`, `session.ended`
5. Repeat from step 2 for next session

## 🔗 Related Documentation

- [SESSION_START_WEBSOCKET.md](SESSION_START_WEBSOCKET.md) - session.started event details
- [SESSION_END_WEBSOCKET.md](SESSION_END_WEBSOCKET.md) - session.ended event details
- [API_QUICK_REFERENCE.md](API_QUICK_REFERENCE.md) - API reference
- [BOT_INTEGRATION.md](BOT_INTEGRATION.md) - Bot integration guide

