chat app diagram
┌─────────────────────────────────────────────────────────────────┐
│                        CLIENT (browser)                         │
└────────────┬────────────────────────────┬───────────────────────┘
             │ WebSocket                  │ HTTP REST
             │ ws/chat/<id>/              │ /api/social/
             ▼                            ▼
┌────────────────────────┐   ┌────────────────────────────────────┐
│    ChatConsumer        │   │         REST Views                 │
│  (consumers.py)        │   │         (views.py)                 │
│                        │   │                                    │
│  connect()             │   │  ChatViewSet                       │
│  ├─ auth check         │   │  ├─ list / retrieve    (GET)       │
│  └─ membership check ──┼───┼──► IsChatMember                    │
│                        │   │  ├─ create             (POST)      │
│  receive()             │   │  ├─ update/partial     (PATCH/PUT) │
│  ├─ new_chat_message   │   │  │   └─ CanManageChat              │
│  │  (text only)        │   │  ├─ destroy            (DELETE)    │
│  │   └─► _create_message   │  │   └─ CanManageChat              │
│  │         (DB INSERT) │   │  └─ add/remove member & moderator  │
│  │                     │   │                                    │
│  ├─ new_reply_message  │   │  MessageViewSet                    │
│  │  (text only)        │   │  ├─ list / retrieve    (GET)       │
│  │   └─► _create_message   │  │   └─ IsAuthenticated            │
│  │         (DB INSERT) │   │  ├─ send              (POST)       │
│  │                     │   │  │   ├─ IsAuthenticated            │
│  └─ reaction           │   │  │   ├─ DB INSERT Message          │
│      └─► _toggle_reaction  │  │   ├─ DB INSERT MessageFile(s)   │
│            (DB UPDATE/ │   │  │   └─► group_send(chat.msg) ─────┼──► WebSocket push
│             DELETE)    │   │  ├─ update/partial     (PATCH/PUT) │
│                        │   │  │   ├─ IsMessageSenderOnly        │
│  typing / stop_typing  │   │  │   ├─ message.edit_content()     │
│  └─► group_send only   │   │  │   └─► group_send(edit.msg) ─────┼──► WebSocket push
│      (no DB write)     │   │  └─ destroy            (DELETE)    │
│                        │   │      ├─ CanDeleteMessage           │
│                        │   │      └─► group_send(delete.msg) ───┼──► WebSocket push
└────────────┬───────────┘   └──────────────┬─────────────────────┘
             │                              │
             │  both use channel_layer      │
             ▼                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                    Channel Layer (Redis)                        │
│                   group: "chat_{id}"                            │
└─────────────────────────────────────────────────────────────────┘
             │
             ▼  group_send dispatches to all connected consumers
┌─────────────────────────────────────────────────────────────────┐
│  ChatConsumer event handlers (push to each connected client)    │
│  chat_message · reply_chat_message · edit_message               │
│  delete_message · message_reaction · typing_status · stop_typing│
└─────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────┐   ┌──────────────────────────┐
│  Database writes summary         │   │  When to use which path  │
│                                  │   │                          │
│  CREATE  Message  ← consumer     │   │  WS  ← text-only msg     │
│                      (text only) │   │  HTTP← msg with files    │
│  CREATE  Message  ← view /send   │   │  HTTP← edit message      │
│                      (any)       │   │  HTTP← delete message    │
│  CREATE  MessageFile ← view/send │   │  WS  ← reaction          │
│  UPDATE  Message  ← view         │   │  WS  ← typing indicator  │
│  DELETE  Message  ← view (soft)  │   └──────────────────────────┘
│  CREATE  MessageReaction ← cons  │
│  UPDATE  MessageReaction ← cons  │
│  DELETE  MessageReaction ← cons  │
│  CREATE  MessageHistory  ← model │
│          (auto on edit_content)  │
└──────────────────────────────────┘
