# 01 - Conversation & Message Database Persistence

Welcome to **Milestone 2, Step 2.2**: Conversation & Message Database Persistence & State-Based Message Routing.

---

## 1. Conversation vs. Message Collections

In MongoDB, chat data is structured hierarchically across two collections:

- **Conversations Collection (`conversations`):** Represents the top-level chat thread.
  - Fields: `conversationId`, `sessionId`, `siteId`, `status` (`"open"` | `"ended"`), `endedBy` (`"visitor"` | `"agent"`), `createdAt`, `updatedAt`.
- **Messages Collection (`messages`):** Represents individual user/agent/assistant chat entries.
  - Fields: `messageId`, `conversationId`, `sessionId`, `role` (`"user"` | `"agent"` | `"assistant"`), `content`, `createdAt`.

---

## 2. Phase 1 Rule: ONE SESSION = ONE CONVERSATION

Each visitor session maps to exactly **one active conversation thread**:

```text
  Session (sessionId: sess_123)
     │
     └── Conversation (conversationId: conv_456, siteId: site_demo, status: "open")
           │
           ├── User Message ("Hello", role: "user")
           └── Agent Message ("Hi! How can I help?", role: "agent")
```

---

## 3. State-Based Visitor Message Routing (`POST /api/v1/message`)

When a visitor submits a message via `POST /api/v1/message`, the backend checks current session status (`RINGING`, `IN_CHAT`, or `ENDED`) and handles it accordingly:

```text
                           POST /api/v1/message
                                    │
                        [Validate Session in DB]
                                    │
                        [Check current_status]
         ┌──────────────────────────┼──────────────────────────┐
         ▼                          ▼                          ▼
    [RINGING Mode]           [IN_CHAT Mode]              [ENDED Mode]
         │                          │                          │
 1. Persist Visitor Msg     1. Persist Visitor Msg      Reject with HTTP 400
 2. Broadcast to Agents     2. Broadcast to Agents      "Cannot send message
 3. Suppress Bot Echo       3. Return "Message          to an ended session"
 4. Return "Please wait        delivered to agent."
    while we connect..."
```

### Exact State Responses

1. **`RINGING` State:**
   - Visitor message persisted in MongoDB (`role: "user"`).
   - Broadcast live to active Agent Dashboards (`user_message` WS event).
   - **No** Echo assistant message is created or saved to MongoDB.
   - Response: `{"sessionId": "sess_123", "reply": "Please wait while we connect you to an agent."}`

2. **`IN_CHAT` State:**
   - Visitor message persisted in MongoDB (`role: "user"`).
   - Broadcast live to active Agent Dashboards (`user_message` WS event).
   - Response: `{"sessionId": "sess_123", "reply": "Message delivered to agent."}`

3. **`ENDED` State:**
   - Rejected with **`HTTP 400 Bad Request`**: `{"detail": "Cannot send message to an ended session 'sess_123'"}`.

---

## 4. Agent Message Endpoint (`POST /api/v1/handoff/message`)

When an agent replies via `POST /api/v1/handoff/message`:
- **Active Chat (`IN_CHAT` / `RINGING`):** Persists agent message in MongoDB (`role: "agent"`), delivers real-time payload via WebSocket to visitor socket (`agent_message`), and broadcasts to agent dashboards.
- **Ended Chat (`ENDED`):** Rejects immediately with **`HTTP 400 Bad Request`**.
