# SMS Delivery Tracking Documentation

## Aperçu
Le système envoie automatiquement des SMS de confirmation de rendez-vous via Twilio et suit leur statut de livraison en temps réel grâce aux webhooks de callback.

## Fonctionnalités

### 1. Envoi automatique de SMS
Lorsqu'un patient confirme un rendez-vous via le voicebot, un SMS de confirmation est automatiquement envoyé avec :
- Nom du patient
- Nom du médecin
- Date et heure du rendez-vous (formaté en français)

**Exemple de message :**
```
Bonjour Marie Dupont,

Votre rendez-vous avec Dr. Martin est confirmé pour le mardi 22 octobre 2025 à 14:30.

Merci de nous avoir contactés.
```

### 2. Tracking du statut de livraison

#### Champs dans la base de données (`InboundCallRequest`)
- `smsSent` (boolean) : Indique si un SMS a été envoyé
- `smsSid` (varchar 50) : L'identifiant unique Twilio du message
- `smsStatus` (varchar 20) : Le statut actuel du SMS

#### Statuts possibles
- `queued` : En attente d'envoi
- `sent` : Envoyé par Twilio
- `delivered` : Délivré au destinataire
- `failed` : Échec de livraison
- `undelivered` : Non délivré

### 3. Webhook de callback Twilio

**Endpoint :** `POST /api/voip/sms/status-callback`

**Sécurité :** Public (nécessaire pour les webhooks Twilio)

**Paramètres reçus :**
- `MessageSid` : Identifiant du message
- `MessageStatus` : Nouveau statut
- `From` : Numéro expéditeur
- `To` : Numéro destinataire
- `ErrorCode` (optionnel) : Code d'erreur si échec

**Fonctionnement :**
1. Twilio envoie les mises à jour de statut à cet endpoint
2. Le système recherche le SMS via `messageSid`
3. Met à jour le statut dans la base de données
4. Logs l'événement

## Configuration requise

### Variables d'environnement (.env)

```bash
# URL de base pour les webhooks (ngrok en local)
SERVER_BASE_URL=https://your-ngrok-url.ngrok.io

# Twilio (déjà configuré)
TWILIO_ACCOUNT_SID=your-account-sid
TWILIO_AUTH_TOKEN=your-auth-token
TWILIO_PHONE_NUMBER=+1234567890
```

### Configuration Twilio Dashboard

⚠️ **Note importante** : Vous n'avez PAS besoin de configurer le callback dans Twilio Dashboard car il est automatiquement ajouté lors de l'envoi du SMS via l'API.

Si vous voulez quand même le configurer globalement :
1. Aller dans Twilio Console > Phone Numbers
2. Sélectionner votre numéro Twilio
3. Dans "Messaging Configuration" :
   - **Status Callback URL** : `{SERVER_BASE_URL}/api/voip/sms/status-callback`
   - **HTTP Method** : POST

**L'URL de callback est la même pour tous les tenants** - le système identifie automatiquement le tenant via le numéro Twilio.

## Test en local avec ngrok

### 1. Démarrer ngrok
```bash
ngrok http 8000
```

### 2. Mettre à jour .env
Copier l'URL ngrok (ex: `https://abc123.ngrok.io`) dans `SERVER_BASE_URL`

### 3. Vérifier les logs
```bash
# Dans les logs Spring Boot, chercher :
📨 SMS envoyé avec succès ! SID: SM123... | Statut: queued
📍 SMS Status Callback URL set: https://abc123.ngrok.io/api/voip/sms/status-callback

# Plus tard, lors des callbacks :
📬 Callback SMS reçu - SID: SM123... | Statut: delivered
✅ Statut SMS mis à jour : SM123... -> delivered
```

### 4. Vérifier dans la base de données
```sql
SELECT call_sid, sms_sent, sms_sid, sms_status, patient_phone 
FROM inbound_call_requests 
WHERE sms_sent = true 
ORDER BY created_at DESC;
```

## Architecture multi-tenant

✅ **Solution implémentée : Identification automatique via le numéro Twilio**

Le système identifie automatiquement le tenant en utilisant le numéro Twilio présent dans le callback :

### Flux d'identification du tenant

1. **Callback Twilio arrive** avec les paramètres :
   - `From` : Le numéro Twilio (ex: +1234567890)
   - `MessageSid` : L'ID du message
   - `MessageStatus` : Le statut (queued, sent, delivered, failed)

2. **Lookup du tenant** :
   ```java
   // STEP 1: Chercher dans la table admin TwilioPhoneNumber
   TenantContext.setTenantId("admin");
   Optional<TwilioPhoneNumber> phone = twilioPhoneNumberRepository.findByPhoneNumber(from);
   String tenantId = phone.getTenantId(); // ex: "acme_corp"
   
   // STEP 2: Récupérer le schéma depuis la table Tenant
   Optional<Tenant> tenant = tenantRepository.findByTenantId(tenantId);
   String schemaName = tenant.getSchemaName(); // ex: "tenant_acme_corp"
   
   // STEP 3: Switch vers le schéma tenant
   TenantContext.setTenantId(schemaName);
   
   // STEP 4: Mettre à jour le statut SMS
   inboundCallService.updateSmsStatus(messageSid, messageStatus);
   ```

3. **Avantages** :
   - ✅ Pas besoin de paramètres dans l'URL
   - ✅ Une seule URL de callback pour tous les tenants
   - ✅ Identification automatique et sécurisée
   - ✅ Compatible avec l'architecture existante (même logique que les appels entrants)

## Débogage

### Problèmes courants

1. **Callback non reçu**
   - Vérifier que ngrok est actif
   - Vérifier l'URL dans Twilio Dashboard
   - Vérifier les logs Twilio (Console > Monitor > Logs)

2. **Statut non mis à jour**
   - Vérifier que `messageSid` correspond
   - Vérifier les logs d'erreur Spring Boot
   - Vérifier que le service InboundCallService peut trouver le call

3. **Erreur 404 sur callback**
   - Vérifier que l'endpoint est public dans SecurityConfig
   - Vérifier l'URL exacte dans Twilio

### Logs utiles
```java
// Dans TwilioSmsCallbackController
log.info("📬 Callback SMS reçu - SID: {} | Statut: {}", messageSid, messageStatus);

// Dans InboundCallService
log.info("✅ Statut SMS mis à jour : {} -> {}", messageSid, newStatus);
```

## Évolutions futures

1. **Retry logic** : Renvoyer automatiquement les SMS échoués
2. **Notifications** : Alerter l'admin si trop de SMS échouent
3. **Analytics** : Dashboard de taux de livraison par tenant
4. **Multi-canal** : Support WhatsApp, email en plus des SMS
