# Meta Cloud API — WhatsApp Webhook Setup

## Resumen

Vale usa Meta Cloud API (Graph API v25.0) para recibir y enviar mensajes de WhatsApp.
El token de acceso de cada tenant se guarda **cifrado** (AES-256-GCM) en `tenant_whatsapp.access_token`.
Nunca se versiona ni se hardcodea.

---

## Variables de entorno requeridas

```env
# Secreto del webhook (vos lo elegís, debe coincidir con Meta → Webhooks → Verify Token)
META_WEBHOOK_VERIFY_TOKEN=vale_meta_2026

# App Secret para validar firma de webhooks (Meta App → Configuración básica → App Secret)
META_APP_SECRET=

# Token del número de prueba (solo para correr el seed; no se usa en runtime)
META_TEST_TOKEN=EAAOJmf...

# Clave AES-256-GCM para cifrar tokens en DB
# Generar: php -r "echo base64_encode(random_bytes(32)) . PHP_EOL;"
TOKEN_ENCRYPTION_KEY=
```

---

## Setup paso a paso

### 1. Migraciones SQL (phpMyAdmin o terminal)

Ejecutar en orden desde la raíz del proyecto:

```
migrations/013_agent_config.sql
migrations/014_meta_webhook.sql
migrations/015_tenant_whatsapp.sql
```

**Error frecuente:** `#1060 - Duplicate column name` → la migración ya fue aplicada antes. Ignorar y continuar con la siguiente.

### 2. Generar TOKEN_ENCRYPTION_KEY

```bash
php -r "echo base64_encode(random_bytes(32)) . PHP_EOL;"
```

Pegá el resultado en `.env` como `TOKEN_ENCRYPTION_KEY=...`

**Error frecuente:** `TOKEN_ENCRYPTION_KEY must be 32 raw bytes, base64-encoded`
→ El valor en `.env` tiene espacios, comillas o fue truncado. Regenerar con el comando de arriba.

### 3. Obtener META_TEST_TOKEN

Meta Developer Console → tu app → WhatsApp → Configuración de la API → Token de acceso.

> **Importante:** ese token es temporal (expira en horas/días). Para producción generar un token permanente desde Business Manager → Usuarios del sistema.

### 4. Correr el seed

```bash
cd /home/supraide/public_html/vale.supraide.com
php migrations/seed_meta_demo.php
```

Output esperado:
```
OK: tenant_whatsapp seed completado.
    tenant_id      = 1 (Barber Shop)
    phone_number_id= 1215781871610651
    waba_id        = 2131234881066413
    access_token   = [cifrado]
```

**Error frecuente:** `META_TEST_TOKEN no está definido en .env`
→ Agregar al `.env`: `echo "META_TEST_TOKEN=EAAOJmf..." >> .env`

**Error frecuente:** `No hay tenants en la DB`
→ Completar el onboarding en la app primero para crear el primer tenant.

### 5. Configurar webhook en Meta

- URL: `https://vale.supraide.com/webhook/meta`
- Verify Token: el valor de `META_WEBHOOK_VERIFY_TOKEN` en `.env`
- Suscribirse al campo: **`messages`**

**Error frecuente:** "No se pudo validar la URL"
→ El código no está deployado en el servidor. Verificar con:
```bash
curl "https://vale.supraide.com/webhook/meta?hub_mode=subscribe&hub_verify_token=vale_meta_2026&hub_challenge=TEST"
# Debe devolver: TEST
```

### 6. Probar

En Meta → WhatsApp → Configuración de la API → agregar tu número personal como destinatario de prueba → "Enviar mensaje".
Una vez recibido el mensaje, **respondés vos** → Vale contesta automáticamente.

---

## Multi-tenant: agregar un nuevo negocio con WhatsApp

Cada negocio necesita su propio número de WhatsApp Business registrado en Meta.

### Paso 1 — Obtener los datos del número

En Meta → WhatsApp → Configuración de la API → seleccionar el número del negocio:
- `phone_number_id`
- `waba_id`
- Token de acceso

### Paso 2 — Correr el seed para ese tenant

```bash
php migrations/seed_meta_demo.php --tenant=ID_DEL_TENANT --pid=PHONE_NUMBER_ID --waba=WABA_ID
```

(Ver sección de mejoras del seed abajo)

### Paso 3 — Verificar

```bash
php migrations/verify_meta_setup.php
```

---

## Arquitectura del flujo

```
Cliente WhatsApp
      │
      ▼
META Cloud API
      │  POST JSON
      ▼
/webhook/meta  (agent_meta.php)
      │
      ├─ Valida firma X-Hub-Signature-256
      ├─ Extrae phone_number_id + mensaje
      ├─ Busca tenant en tenant_whatsapp por phone_number_id
      ├─ Descifra access_token (AES-256-GCM)
      ├─ Persiste mensaje en messages
      ├─ Actualiza window_expires_at (+24h)
      │
      ▼
AgentService::handleMessage()
      │
      ├─ Carga vale_config (knowledge, guardrails, etc.)
      ├─ Llama Gemini con historial + tools
      ├─ Ejecuta function calls (get_availability, crear_cita, escalate_to_owner)
      │
      ▼
MetaWhatsApp::sendText()
      │  POST /v25.0/{phone_number_id}/messages
      ▼
META Cloud API → Cliente WhatsApp
```

---

## Tabla tenant_whatsapp

| Columna | Tipo | Descripción |
|---|---|---|
| tenant_id | FK | Negocio dueño |
| provider | ENUM | `meta` o `twilio` |
| phone_number_id | VARCHAR(64) | ID del número en Meta (no es el número en sí) |
| waba_id | VARCHAR(64) | ID de la cuenta de WhatsApp Business |
| access_token | TEXT | Token cifrado con AES-256-GCM |
| status | ENUM | `active`, `inactive`, `suspended` |

---

## Errores conocidos y soluciones

| Error | Causa | Solución |
|---|---|---|
| `#1060 Duplicate column name` | Migración ya aplicada | Ignorar, continuar |
| `TOKEN_ENCRYPTION_KEY must be 32 raw bytes` | Key inválida o truncada | Regenerar con `php -r "echo base64_encode(random_bytes(32)) . PHP_EOL;"` |
| `META_TEST_TOKEN no está definido` | Falta en `.env` | `echo "META_TEST_TOKEN=EAAxx" >> .env` |
| `tenant no encontrado para phone_number_id` | Seed no corrido o phone_number_id incorrecto | Correr seed con el ID correcto |
| 404 en `/webhook/meta` | Código no deployado | Subir archivos al servidor |
| Token decrypt failed | TOKEN_ENCRYPTION_KEY cambió después del seed | Re-correr el seed con la key correcta |
