# KYC Socket.IO Integration — Flutter Driver App

## Connection

```
URL:  http://<server_ip>:<port>
Lib:  socket_io_client (Flutter)
```

### Connect & Register

After socket connects, **immediately emit `register`** with the driver's UUID.  
This maps the driver's socket to their ID on the server — required for all KYC events to reach the driver.

```dart
socket.on('connect', (_) {
  socket.emitWithAck('register', driverUUID, ack: (res) {
    // res: { status: 'success', message: 'User registered successfully' }
  });
});
```

---

## PHASE 1 — Queue Management

### 1. Join KYC Queue

**Emit:** `kyc_join_queue`

```dart
socket.emitWithAck('kyc_join_queue', { 'driver_id': driverUUID }, ack: (res) {
  // res.status == 'success'
  // res.data:
  // {
  //   token_no: 7,
  //   position: 1,
  //   people_ahead: 0,
  //   estimated_wait_minutes: 0,
  //   queue_stats: { total_waiting: 1, ... }
  // }
  // Error: res.status == 'error', res.message == 'KYC already completed'
});
```

---

### 2. Get Queue Status

**Emit:** `kyc_get_queue_status`

```dart
socket.emitWithAck('kyc_get_queue_status', { 'driver_id': driverUUID }, ack: (res) {
  // res.data:
  // {
  //   token_no: 7,
  //   position: 1,
  //   people_ahead: 0,
  //   estimated_wait_minutes: 0,
  //   waiting_since_minutes: 3,
  //   queue_stats: { ... }
  // }
  // Error: res.message == 'Not in queue'
});
```

---

### 3. Leave Queue

**Emit:** `kyc_leave_queue`

```dart
socket.emitWithAck('kyc_leave_queue', { 'driver_id': driverUUID }, ack: (res) {
  // res.status == 'success'
  // res.data: { token_no: 7 }
});
```

---

### 4. Listen — Queue Position Updated

**Listen:** `kyc_queue_updated`  
Broadcast to all — fires whenever anyone joins/leaves queue.

```dart
socket.on('kyc_queue_updated', (data) {
  // data: { total_waiting: 3, ... }
  // Re-call kyc_get_queue_status to refresh driver's own position
});
```

---

## PHASE 2 — Session Called by Admin

### 5. Listen — Session Started (Admin called this driver)

**Listen:** `kyc_session_started`  
Also delivered via **FCM push notification** when app is in background.

```dart
socket.on('kyc_session_started', (data) {
  // data:
  // {
  //   session_id: 'kyc_1234567890_abc12345',
  //   admin_id: 1,
  //   token_no: 7,
  //   message: 'Your KYC session has started. Please join the video call.'
  // }

  // → Save session_id
  // → Navigate driver to KYC video screen
  // → Call kyc_join_session (see event 6)
});
```

> **FCM Note:** `data` payload in FCM notification also contains `session_id`, `admin_id`, `token_no`.  
> When driver taps notification, extract `session_id` from FCM data and proceed to join session.

---

### 6. Join Session Room

**Emit:** `kyc_join_session`  
Must be called after receiving `kyc_session_started`, before WebRTC.

```dart
socket.emitWithAck('kyc_join_session', {
  'session_id': sessionId,
  'user_id': driverUUID,
  'user_type': 'driver'
}, ack: (res) {
  // res.status == 'success'
  // res.data:
  // {
  //   session_id: 'kyc_...',
  //   current_step: 'introduction',
  //   driver_name: 'Ravi Kumar',
  //   token_no: 7
  // }

  // → Initialize WebRTC (camera + mic)
  // → Wait for incoming_call from admin
});
```

---

## PHASE 3 — WebRTC Video Call

> Admin always initiates the WebRTC offer. Driver answers.  
> Driver sends **video + audio**. Admin sends **audio only**.

### 7. Listen — Incoming WebRTC Call

**Listen:** `incoming_call`

```dart
socket.on('incoming_call', (data) {
  // data:
  // {
  //   fromUserId: 1,       // admin_id (integer)
  //   offer: { ... }       // RTCSessionDescription (SDP offer)
  // }

  // → Save fromUserId as currentAdminId
  // → setRemoteDescription(offer)
  // → createAnswer()
  // → setLocalDescription(answer)
  // → emit answer_call (see event 8)
});
```

---

### 8. Send WebRTC Answer

**Emit:** `answer_call`

```dart
socket.emitWithAck('answer_call', {
  'fromUserId': driverUUID,   // driver's own UUID
  'toUserId': adminId,        // integer admin ID received in incoming_call
  'answer': rtcAnswer         // RTCSessionDescription answer object
}, ack: (res) {
  // res.status == 'success'
});
```

---

### 9. Send ICE Candidate

**Emit:** `ice_candidate`

```dart
socket.emit('ice_candidate', {
  'fromUserId': driverUUID,
  'toUserId': adminId,
  'candidate': iceCandidate   // RTCIceCandidate object
});
```

---

### 10. Listen — ICE Candidate from Admin

**Listen:** `ice_candidate`

```dart
socket.on('ice_candidate', (data) {
  // data: { candidate: RTCIceCandidate, fromUserId: adminId }
  // → peerConnection.addIceCandidate(data['candidate'])
});
```

---

## PHASE 4 — Live Session Events

### 11. Listen — Step Changed by Admin

**Listen:** `kyc_step_changed`

```dart
socket.on('kyc_step_changed', (data) {
  // data:
  // {
  //   session_id: 'kyc_...',
  //   step: 'show_aadhar',
  //   instruction: 'Please show your Aadhar card clearly in the frame',
  //   changed_by: 1,
  //   timestamp: 1234567890
  // }

  // Possible step values:
  // 'introduction'  → 'Please look at the camera and introduce yourself'
  // 'show_aadhar'   → 'Please show your Aadhar card clearly in the frame'
  // 'show_pan'      → 'Please show your PAN card clearly in the frame'
  // 'show_license'  → 'Please show your Driving License clearly in the frame'
  // 'show_rc'       → 'Please show your Vehicle RC clearly in the frame'
  // 'show_signature'→ 'Please show your Signature clearly in the frame'
  // 'show_vehicle'  → 'Please show your Vehicle clearly in the frame'
  // 'session_complete' → 'Thank you! Your KYC session is complete'

  // → Show instruction text to driver on screen
  // → Highlight current step in UI
});
```

---

### 12. Listen — Document Captured by Admin

**Listen:** `kyc_document_captured`

```dart
socket.on('kyc_document_captured', (data) {
  // data:
  // {
  //   session_id: 'kyc_...',
  //   doc_type: 'aadhar',    // face | aadhar | pan | driving_license | vehicle_rc | signature | vehicle_photo
  //   captured_by: 1,
  //   timestamp: 1234567890
  // }

  // → Show toast: 'Aadhar captured successfully'
});
```

---

### 13. Listen — Switch Camera (Admin requested)

**Listen:** `kyc_switch_camera`

```dart
socket.on('kyc_switch_camera', (data) {
  // data: { session_id: 'kyc_...' }

  // → Switch between front and back camera
  // → Replace video track in RTCPeerConnection via replaceTrack()
});
```

---

### 14. Listen — Recording Started

**Listen:** `kyc_recording_started`

```dart
socket.on('kyc_recording_started', (data) {
  // data:
  // {
  //   session_id: 'kyc_...',
  //   started_by: 1,
  //   timestamp: 1234567890
  // }

  // → Show recording indicator in UI (red dot / REC badge)
});
```

---

### 15. Listen — Recording Stopped

**Listen:** `kyc_recording_stopped`

```dart
socket.on('kyc_recording_stopped', (data) {
  // data:
  // {
  //   session_id: 'kyc_...',
  //   stopped_by: 1,
  //   timestamp: 1234567890
  // }

  // → Hide recording indicator
});
```

---

### 16. Listen — Session Ended by Admin

**Listen:** `kyc_session_ended`  
Also delivered via **FCM push notification**.

```dart
socket.on('kyc_session_ended', (data) {
  // data:
  // {
  //   session_id: 'kyc_...',
  //   status: 'pending_review',
  //   message: 'Your KYC session is complete. We will review and notify you soon.'
  // }

  // → Stop camera and mic
  // → Close RTCPeerConnection
  // → Show 'Under Review' screen to driver
});
```

---

## PHASE 5 — KYC Decision (After Admin Review)

### 17. Listen — KYC Decision

**Listen:** `kyc_decision`  
Also delivered via **FCM push notification**.

```dart
socket.on('kyc_decision', (data) {
  // data:
  // {
  //   session_id: 'kyc_...',
  //   decision: 'approved',          // 'approved' or 'rejected'
  //   rejection_reason: null          // string if rejected, null if approved
  // }

  // → If approved: show success screen, allow driver to go online
  // → If rejected: show rejection reason, contact support option
});
```

---

## Complete Flow Diagram

```
Driver App                          Server                        Admin Panel
    |                                  |                               |
    |--- register(driverUUID) -------->|                               |
    |<-- ack: success -----------------|                               |
    |                                  |                               |
    |--- kyc_join_queue(driver_id) --->|                               |
    |<-- ack: token_no, position ------|                               |
    |                                  |<-- kyc_call_next_driver ------|
    |<-- kyc_session_started ----------|                               |
    |  (also via FCM)                  |                               |
    |                                  |                               |
    |--- kyc_join_session ------------>|                               |
    |<-- ack: current_step ------------|                               |
    |                                  |-----> kyc_user_joined ------->|
    |                                  |                               |
    |                                  |<-- kyc_call_user (WebRTC) ----|
    |<-- incoming_call (SDP offer) ----|                               |
    |                                  |                               |
    |--- answer_call (SDP answer) ---->|                               |
    |<-> ice_candidate (both ways) --->|<---------------------------- |
    |                                  |                               |
    |  [VIDEO CALL ACTIVE]             |                               |
    |                                  |                               |
    |<-- kyc_step_changed -------------|<-- kyc_step_change -----------|
    |<-- kyc_document_captured --------|<-- kyc_save_photo ------------|
    |<-- kyc_switch_camera ------------|<-- kyc_switch_camera ---------|
    |<-- kyc_recording_started --------|<-- kyc_recording_start -------|
    |<-- kyc_recording_stopped --------|<-- kyc_recording_stop --------|
    |                                  |                               |
    |<-- kyc_session_ended ------------|<-- kyc_end_session -----------|
    |  (also via FCM)                  |                               |
    |                                  |                               |
    |<-- kyc_decision -----------------|<-- (admin review panel) ------|
    |  (also via FCM)                  |                               |
```

---

## TURN/ICE Server Config

```dart
final iceConfig = {
  'iceServers': [
    { 'urls': 'stun:stun.l.google.com:19302' },
    {
      'urls': [
        'turn:103.211.202.56:5050?transport=udp',
        'turn:103.211.202.56:5050?transport=tcp'
      ],
      'username': 'bitspan',
      'credential': 'Bitspan!202BINDSecure'
    }
  ]
};
```

---

## Events Summary Table

| # | Event Name | Direction | When |
|---|-----------|-----------|------|
| 1 | `register` | Emit | On socket connect |
| 2 | `kyc_join_queue` | Emit | Driver requests KYC |
| 3 | `kyc_get_queue_status` | Emit | Refresh position |
| 4 | `kyc_leave_queue` | Emit | Driver cancels |
| 5 | `kyc_queue_updated` | Listen | Queue changed |
| 6 | `kyc_session_started` | Listen + FCM | Admin called driver |
| 7 | `kyc_join_session` | Emit | After session started |
| 8 | `incoming_call` | Listen | Admin sends WebRTC offer |
| 9 | `answer_call` | Emit | Driver sends WebRTC answer |
| 10 | `ice_candidate` | Emit | Driver's ICE candidates |
| 11 | `ice_candidate` | Listen | Admin's ICE candidates |
| 12 | `kyc_step_changed` | Listen | Admin changed step |
| 13 | `kyc_document_captured` | Listen | Admin captured a doc |
| 14 | `kyc_switch_camera` | Listen | Admin wants camera switch |
| 15 | `kyc_recording_started` | Listen | Admin started recording |
| 16 | `kyc_recording_stopped` | Listen | Admin stopped recording |
| 17 | `kyc_session_ended` | Listen + FCM | Admin ended session |
| 18 | `kyc_decision` | Listen + FCM | KYC approved/rejected |
