# WhatsApp Cloud API Debugging - Complete Implementation

## Problem Summary

WhatsApp Cloud API returns HTTP 200 with a wamid, but recipients don't receive messages.

**Root Cause:** The initial API response (HTTP 200) only means Meta **accepted** the message, NOT that it was delivered. The actual delivery status comes from **webhook callbacks** which were not implemented.

---

## Solution Implemented

### 1. ✅ Message Status Tracking

**File:** `models.py`

Added `WhatsAppMessage` model to track:
- `wamid` - WhatsApp message ID from Meta
- `status` - sent, delivered, read, failed
- `event_id`, `guest_id` - Context for tracking
- `error_code`, `error_title`, `error_message` - Failure details
- Timestamps: `sent_at`, `delivered_at`, `read_at`, `failed_at`

### 2. ✅ Webhook Endpoint

**File:** `main.py`

Added two webhook endpoints:

```python
GET  /whatsapp/webhook  # Webhook verification
POST /whatsapp/webhook  # Status updates from Meta
```

**What it does:**
- Receives delivery status updates from Meta
- Updates message status in database
- Logs all webhook payloads for debugging
- Handles: sent, delivered, read, failed statuses
- Captures error details when messages fail

### 3. ✅ Enhanced WhatsApp Service

**File:** `whatsapp.py`

**Changes:**
1. Added `event_id` and `guest_id` parameters to `send_by_template_key()`
2. Saves messages to database after sending
3. Supports dynamic image headers via `header_handle_key`
4. Enhanced logging with full payload dumps

### 4. ✅ Fixed hina_invitation Template

**File:** `whatsapp_templates.py`

**Configuration:**
```python
{
    "meta_name": "hina_invitation",
    "language_code": "he",
    "header_type": "IMAGE",
    "header_handle_key": "invitation_image_url",  # Dynamic image from params
    "body_params": ["contact_name"],
    "button_type": "URL",
    "button_url": "https://invy.dvirlabs.com/guest/{{1}}",
    "button_param_key": "event_id",
}
```

### 5. ✅ Comprehensive Test Script

**File:** `test_whatsapp_debug.py`

**Features:**
- Tests phone normalization
- Validates template configuration
- Sends test message with full logging
- Shows webhook setup instructions
- Provides clear debugging output

### 6. ✅ Database Migration

**File:** `add_whatsapp_messages_table.py`

Creates the `whatsapp_messages` table.

---

## Setup Instructions

### Step 1: Run Database Migration

```bash
cd backend
python add_whatsapp_messages_table.py
```

### Step 2: Configure Webhook in Meta Business Manager

1. Go to **Meta Business Manager** → **WhatsApp** → **Configuration** → **Webhook**

2. **Callback URL:**
   ```
   https://invy.dvirlabs.com/whatsapp/webhook
   ```

3. **Verify Token:** 
   - Set this in `.env` as `WHATSAPP_VERIFY_TOKEN=your_secret_token_here`
   - Use the same value in Meta's webhook configuration

4. Click **Verify and Save**

5. **Subscribe to Fields:**
   - ✅ messages

### Step 3: Update Environment Variables

Add to `.env`:
```bash
# Existing WhatsApp credentials
WHATSAPP_ACCESS_TOKEN=your_meta_access_token
WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id
WHATSAPP_API_VERSION=v20.0

# NEW: Webhook verification token
WHATSAPP_VERIFY_TOKEN=your_webhook_secret_token_here
```

### Step 4: Test the Integration

```bash
cd backend
python test_whatsapp_debug.py
```

**What to check:**
1. Phone normalization: ✓ All pass
2. Template configuration: ✓ All correct
3. Message send: ✓ Returns wamid
4. Webhook configured: ✓ Verify token set

### Step 5: Send Test Message

The script will prompt you to send a test message to: `0504370045`

**Expected Result:**
```json
{
  "message_id": "wamid.HBgLOTcyNTA0MzcwMDQ1FQIAERgSQzI4QkE1RkQ5MzFFNTY1RTEwAA==",
  "status": "sent",
  "to": "+972504370045",
  "template": "hina_invitation"
}
```

---

## How to Debug Delivery Issues

### Check 1: Backend Logs

Watch for webhook callbacks:
```bash
tail -f backend.log | grep "WhatsApp Webhook"
```

**Expected logs:**
```
[WhatsApp Webhook] Status update: wamid=xxx, status=delivered
[WhatsApp Webhook] ✓ Updated message xxx to status: delivered
```

### Check 2: Database Status

```sql
SELECT 
    wamid,
    to_phone,
    status,
    template_name,
    sent_at,
    delivered_at,
    failed_at,
    error_code,
    error_message
FROM whatsapp_messages
ORDER BY sent_at DESC
LIMIT 10;
```

**Status meanings:**
- `sent` - Meta accepted the message
- `delivered` - Recipient's phone received it
- `read` - Recipient opened the message
- `failed` - Delivery failed (check error_code/error_message)

### Check 3: Common Failure Reasons

**If status stays "sent" and never reaches "delivered":**

1. **Phone number not on WhatsApp**
   - Error code: 131026
   - Solution: Verify the recipient has WhatsApp

2. **Template parameters mismatch**
   - Error code: 132000
   - Solution: Check template in Meta matches your params

3. **Image URL not accessible**
   - Error code: 132015
   - Solution: Ensure image URL is publicly accessible

4. **Phone number blocked your business**
   - Error code: 131031
   - Solution: Recipient must unblock your business number

5. **Rate limiting**
   - Error code: 130429
   - Solution: Slow down sending rate

### Check 4: Webhook Delivery Test

Test webhook is receiving callbacks:
```bash
curl -X GET "https://invy.dvirlabs.com/whatsapp/webhook?hub.mode=subscribe&hub.verify_token=YOUR_TOKEN&hub.challenge=test123"
```

Expected: `test123` (echo challenge)

---

## Example: Sending hina_invitation

```python
from whatsapp import get_whatsapp_service

service = get_whatsapp_service(db)

params = {
    "contact_name": "איילה חורב",
    "event_id": "f3122a7d-1d7c-4cc1-955d-1c6b7358bd25",
    "invitation_image_url": "https://api-invy.dvirlabs.com/uploads/1d32b5fbab0f494cae443b4188a83ca3.jpg",
}

result = await service.send_by_template_key(
    template_key="hina_invitation",
    to_phone="0504370045",
    params=params,
    event_id="f3122a7d-1d7c-4cc1-955d-1c6b7358bd25",
    guest_id="guest-uuid-here",
)

print(f"Message ID: {result['message_id']}")
```

**Generated payload:**
```json
{
  "messaging_product": "whatsapp",
  "to": "+972504370045",
  "type": "template",
  "template": {
    "name": "hina_invitation",
    "language": { "code": "he" },
    "components": [
      {
        "type": "header",
        "parameters": [{
          "type": "image",
          "image": {
            "link": "https://api-invy.dvirlabs.com/uploads/1d32b5fbab0f494cae443b4188a83ca3.jpg"
          }
        }]
      },
      {
        "type": "body",
        "parameters": [
          { "type": "text", "text": "איילה חורב" }
        ]
      },
      {
        "type": "button",
        "sub_type": "url",
        "index": "0",
        "parameters": [
          { "type": "text", "text": "f3122a7d-1d7c-4cc1-955d-1c6b7358bd25" }
        ]
      }
    ]
  }
}
```

---

## Phone Normalization

**Israeli numbers:**
- `0504370045` → `+972504370045` ✓
- `050-437-0045` → `+972504370045` ✓
- `+972504370045` → `+972504370045` ✓
- `972504370045` → `+972504370045` ✓

---

## Files Modified

1. ✅ `models.py` - Added WhatsAppMessage model
2. ✅ `main.py` - Added webhook endpoints, updated imports
3. ✅ `whatsapp.py` - Added event/guest tracking, dynamic image support
4. ✅ `whatsapp_templates.py` - Fixed hina_invitation template

## Files Created

1. ✅ `test_whatsapp_debug.py` - Comprehensive debugging script
2. ✅ `add_whatsapp_messages_table.py` - Database migration
3. ✅ `WHATSAPP_DEBUGGING.md` - This documentation

---

## Next Steps

1. **Run migration:** `python add_whatsapp_messages_table.py`
2. **Configure webhook in Meta Business Manager**
3. **Set WHATSAPP_VERIFY_TOKEN in .env**
4. **Run test script:** `python test_whatsapp_debug.py`
5. **Monitor webhook logs for delivery status**
6. **Check database for message status updates**

---

## Critical Understanding

**HTTP 200 ≠ Message Delivered**

When Meta returns HTTP 200, it means:
- ✓ Request was valid
- ✓ Message was queued for delivery
- ✗ **NOT** that the recipient received it

**Actual delivery confirmation comes from webhook callbacks.**

Without webhooks, you'll never know if messages were delivered, read, or failed.

**This is why webhook implementation is CRITICAL.**
