# PRD: Mitra Chat Request Overlay & Pairing UX

# Overview

**Goal:** Reliable incoming chat request experience for Mitra — always visible, non-blocking, works in all app states (foreground, background, killed)

**Success looks like:** When a customer requests a chat, the mitra is always notified and can accept/reject without leaving their current screen. The notification works regardless of whether the app is in foreground, background, or opened from a push notification.

## Background
- Current bottom sheet approach (`showModalBottomSheet`) fails silently when the app is backgrounded
- Flutter UI cannot render when the app is not in foreground
- Push notifications work in background but the in-app response (bottom sheet) doesn't show reliably when the user taps the notification
- The state change from WebSocket gets "consumed" by listeners while backgrounded, so returning to foreground shows stale data
- Need a solution that is non-blocking (doesn't interrupt active chat sessions) and works on any page


# Functional Requirement

## Incoming Chat Request Overlay

### Trigger
- Overlay watches `chatRequestProvider` state — it does NOT depend on any specific page or lifecycle event
- Three sources can trigger the overlay:
    1. **WebSocket** — real-time delivery when app is in foreground
    2. **FCM notification tap** — user taps push notification, app opens, state is set from notification payload
    3. **App resume** — app returns to foreground, validates pending request with backend

### Appearance
- Slides up from the bottom of the screen, like a bottom sheet
- Rounded top corners
- Page behind is partially dimmed to get mitra's attention
- Shows on top of ANY page (home, chat, history, settings, etc.)

### Content
- Session information (duration, etc.)
- Accept button
- Reject button
- Swipe down to close (= ignore, NOT reject)

### Behavior
- **Accept** → overlay dismisses, navigate to chat session with customer
- **Reject** → overlay dismisses, mitra continues what they were doing
- **Swipe down / close** → overlay dismisses, request is ignored (no explicit reject sent to backend)
- **Request cancelled by customer** → overlay updates to show "Permintaan dibatalkan oleh customer"
- **Request accepted by other mitra** → overlay updates to show "Permintaan diterima oleh Bestie lain"
- **Request expired (60s timeout)** → overlay updates to show "Permintaan kedaluwarsa"
- Stale messages do NOT auto-dismiss — mitra must acknowledge by tapping OK or swiping down

### Multiple Requests
- Show one request at a time
- Requests are queued — when current request is resolved (accepted/rejected/ignored/expired), next queued request appears
- Future enhancement: dedicated `/chat-requests` page with full list

## Push Notification (Background/Killed)

### When App is Backgrounded
- Local notification with sound + vibration (already implemented via WebSocket listener)
- FCM push notification as fallback when WebSocket is disconnected

### When Notification is Tapped
- App opens → `chatRequestProvider` state is set from notification payload (`session_id`)
- Overlay appears with the request detail
- Backend validation confirms request is still pending before showing accept/reject

### Stale Notification Handling
- If user taps a notification for an already-resolved request, overlay shows appropriate message ("dibatalkan" / "diterima Bestie lain" / "kedaluwarsa") then auto-dismisses


## Mitra Request Activity Log

### Goal
Track every mitra's response to incoming chat requests for QC measurement — how many accepted, rejected, ignored (expired without action), and how many active sessions they had at the time.

### Logged Data
For each incoming request delivered to a mitra, log:
- `mitra_id` — which mitra received the request
- `session_id` — which chat request
- `response` — `accepted`, `rejected`, `ignored` (expired without action), `missed` (taken by other mitra before response)
- `response_time_seconds` — how long it took the mitra to respond (null if ignored)
- `active_session_count` — how many active sessions the mitra had at the time of the request
- `notified_at` — when the request was delivered to the mitra
- `responded_at` — when the mitra responded (null if ignored)

### When to Log
All logging is **backend-side and event-driven** — no polling or constant monitoring needed. The frontend only triggers `accepted` and `rejected` through existing API calls.

| Response | Triggered by | Frontend action? |
|---|---|---|
| `accepted` | Backend — when mitra calls `POST /:sessionId/accept` | Yes — mitra taps Accept |
| `rejected` | Backend — when mitra calls `POST /:sessionId/decline` | Yes — mitra taps Reject |
| `missed` | Backend — when `acceptPairingRequest` marks other mitras' notifications (another mitra accepted first) | No — fully backend |
| `ignored` | Backend — when `expirePairingRequest` fires after 60s timeout with no response | No — fully backend |

### Existing Infrastructure
The `chat_request_notifications` table already tracks `notified_at`, `response`, `responded_at`. Current changes needed:
- Distinguish `missed` from `ignored` (currently both stored as `ignored`)
- Add `active_session_count` column — recorded when the notification is created
- `response_time_seconds` can be calculated from `responded_at - notified_at` (no new column needed)

### Control Center
- New dedicated page: Mitra Request Activity
- Dashboard: mitra acceptance rate, average response time, rejection count, ignore count per mitra
- Filter by date range and mitra
- Auto-flagging mitras with high rejection/ignore rate is **out of scope** for this phase (planned for future)


## Technical Implementation

### Overlay Component
- Single `OverlayEntry` managed from `main.dart`
- Wrapped around `MaterialApp.router` in a `Stack`
- Watches `chatRequestProvider` — shows/hides based on state
- Uses `AnimatedPositioned` or `SlideTransition` for bottom-up animation
- `GestureDetector` for swipe-to-dismiss

### State Flow
```
WebSocket  ──→
FCM tap    ──→  chatRequestProvider  ──→  Overlay shows/hides
App resume ──→
```

### No Changes Required
- Backend pairing service (already sends WS + FCM)
- Push notification payload (already contains session_id + type)
- Chat request notifier (already manages state from WS + FCM)

### Cleanup from Phase 3.1
- Remove `showModalBottomSheet` for incoming requests from home screen
- Remove `IncomingRequestSheet` widget
- Remove `didChangeAppLifecycleState` incoming request check from home screen


# Tech Stack
- Flutter `Overlay` / `OverlayEntry` or `Stack` with `AnimatedPositioned`
- Existing Riverpod `chatRequestProvider`
- No backend changes
