# Integración con WhatsApp

Es la parte del sistema con más piezas fuera de nuestro control. Buena parte de la configuración vive **en Meta**, no en la base de datos, y eso explica varios comportamientos que de otro modo parecen inexplicables.

## Dos números, una misma cuenta

El laboratorio opera con dos líneas sobre la misma cuenta de WhatsApp Business (WABA):

| Canal | Configuración | Para qué |
|---|---|---|
| Principal | `whatsapp_phone_number_id` | Bot de atención general |
| Turnero | `whatsapp_phone_number_id_turnero` | Consentimientos, encuestas y avisos de turno |

Se elige al construir el servicio:

```php
$wa = new WhatsAppService();           // línea principal
$wa = new WhatsAppService('turnero');  // línea del turnero
```

> Si un mensaje sale por el número equivocado, casi siempre es porque se instanció sin el canal. Es el mismo WABA y el mismo token: **lo único que cambia es el `phone_number_id`**.

## Configuración

Todo en `system_config`:

| Clave | Qué es |
|---|---|
| `whatsapp_token` | Token de acceso a la API |
| `whatsapp_api_url` | URL base de la Cloud API |
| `whatsapp_business_account_id` | Identificador del WABA |
| `whatsapp_phone_number_id` | Número principal |
| `whatsapp_phone_number_id_turnero` | Número del turnero |
| `webhook_verify_token` | Verificación del webhook |

## Plantillas: la parte que no controlamos

Para escribir primero a alguien (fuera de la ventana de 24 horas) hay que usar una **plantilla aprobada por Meta**. `message_templates` guarda una copia local, pero **la copia no manda**: la versión real está en Meta.

Esto tiene una consecuencia importante y poco intuitiva:

> **Las URL de los botones viven en la plantilla, no en nuestro código.**

La plantilla `consentimiento_turno_v2` tiene un botón así:

```
https://erp.laboratorioximenacaicedo.com/form_cliente.php?t={{1}}
```

Nuestro código solo envía el token como `{{1}}`. Cambiar el código **no cambia** el enlace que recibe el paciente: hay que editar la plantilla en el WhatsApp Manager de Meta y esperar la reaprobación.

El único lugar donde sí armamos la URL completa es el **respaldo en texto plano**, que se usa cuando falla el envío por plantilla (`modules/turnero/api/send_consentimiento.php`).

## Por qué el enlace pasa por dos páginas

El botón apunta a `form_cliente.php?t=<UUID>`, pero el consentimiento del turnero lo muestra `ver_formulario_enviado.php?token=<UUID>`.

`form_cliente.php` detecta que el token tiene formato UUID —o sea, que viene del turnero— y redirige. Convive así porque la plantilla ya estaba aprobada apuntando a la página de envíos, y cambiarla obliga a otra ronda de aprobación en Meta.

## Términos y condiciones

Antes de conversar, el bot exige aceptar los términos. El usuario responde **ACEPTO** o **NO ACEPTO**.

La URL del documento está escrita en **dos lugares** y hay que cambiarlos juntos:

| Dónde | Rol |
|---|---|
| `terms_versions.documento_url` | El bot la adjunta al final del mensaje |
| `system_config.terms_message` | Va escrita dentro del texto de bienvenida |

Se vuelve a pedir la aceptación si: nunca aceptó, pasaron más de 6 meses, o hay una versión nueva con `forzar_reenvio`.

## El webhook

Meta envía los mensajes entrantes al webhook, que los registra y se los pasa a `BotService`. Ahí se decide si responde el bot automático o queda para un operador humano, según el estado de la conversación y el horario de atención (`BusinessHoursService`).

## Qué revisar cuando algo falla

| Síntoma | Dónde mirar primero |
|---|---|
| El mensaje sale por el número equivocado | Que se haya pasado `'turnero'` al constructor |
| Un enlace llega roto o apunta mal | La plantilla en Meta, no el código |
| No llega ninguna plantilla | Estado de aprobación en el WhatsApp Manager |
| Falla el envío pero llega un texto plano | Es el respaldo actuando: la plantilla falló |
| El bot no responde | `webhook_logs`, y el horario de atención |
