# 📱 Implementación de WhatsApp en Polaris (RinoTrack)

## Descripción General

El sistema Polaris utiliza la **API de WhatsApp Business de Meta** para enviar notificaciones y códigos de verificación a los usuarios. Esta implementación permite:

1. **Verificación de teléfono en el login** - Los usuarios deben verificar su número de WhatsApp al iniciar sesión
2. **Notificaciones de tareas** - Alertas automáticas cuando se asignan tareas o subtareas

---

## 🔧 Configuración

### Credenciales de la API

Las credenciales se configuran en el archivo `app/services/NotificationService.php`:

```php
// Configuración de WhatsApp API
private $whatsappApiUrl = 'https://graph.facebook.com/v22.0/123349824184206/messages';
private $whatsappToken = 'EAAJilZAtHj3MBO...'; // Token de acceso de Meta
```

### Componentes

| Componente | Valor |
|------------|-------|
| API Version | v22.0 |
| Phone Number ID | 123349824184206 |
| Endpoint | `https://graph.facebook.com/v22.0/{PHONE_NUMBER_ID}/messages` |

---

## 📋 Plantillas de Mensajes

El sistema usa **plantillas pre-aprobadas** en Meta Business Suite:

### 1. `acceso_polaris` (Verificación de Teléfono)

- **Idioma**: `es_MX`
- **Uso**: Enviar códigos de verificación de 6 dígitos
- **Componentes**:
  - Body: Código de verificación
  - Botón URL: Copiar código

```php
$payload = [
    'messaging_product' => 'whatsapp',
    'to' => $phoneNumber,
    'type' => 'template',
    'template' => [
        'name' => 'acceso_polaris',
        'language' => ['code' => 'es_MX'],
        'components' => [
            [
                'type' => 'body',
                'parameters' => [
                    ['type' => 'text', 'text' => $verificationCode]
                ]
            ],
            [
                'type' => 'button',
                'sub_type' => 'url',
                'index' => '0',
                'parameters' => [
                    ['type' => 'text', 'text' => $verificationCode]
                ]
            ]
        ]
    ]
];
```

### 2. `alerta_polaris` (Notificación de Tareas)

- **Idioma**: `en`
- **Uso**: Notificar asignación de tareas/subtareas
- **Parámetros**:
  1. Nombre del usuario
  2. Nombre de la tarea
  3. Nombre del proyecto

```php
$payload = [
    'messaging_product' => 'whatsapp',
    'to' => $phoneNumber,
    'type' => 'template',
    'template' => [
        'name' => 'alerta_polaris',
        'language' => ['code' => 'en'],
        'components' => [
            [
                'type' => 'body',
                'parameters' => [
                    ['type' => 'text', 'text' => $userName],
                    ['type' => 'text', 'text' => $taskName],
                    ['type' => 'text', 'text' => $projectName]
                ]
            ]
        ]
    ]
];
```

---

## 🔐 Flujo de Verificación de Teléfono

### Diagrama de Flujo

```
┌─────────────┐     ┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   Login     │────▶│  Verificar  │────▶│   Enviar    │────▶│  Verificar  │
│  Usuario    │     │   Teléfono? │     │   Código    │     │   Código    │
└─────────────┘     └─────────────┘     └─────────────┘     └─────────────┘
                           │                   │                   │
                           ▼                   ▼                   ▼
                    ¿Es clan_member      WhatsApp API         Guardar tel.
                    o clan_leader        con plantilla        en Users
                    sin teléfono?        acceso_polaris       y completar
                                                              login
```

### Archivos Involucrados

| Archivo | Función |
|---------|---------|
| `app/views/login.php` | Vista del formulario de verificación |
| `app/controllers/AuthController.php` | Controladores de verificación |
| `app/services/NotificationService.php` | Envío de WhatsApp |
| `public/index.php` | Rutas de la API |

### Rutas de API

```php
// Enviar código de verificación
POST ?route=auth/send-phone-verification

// Verificar código ingresado
POST ?route=auth/verify-phone-code

// Reenviar código
POST ?route=auth/resend-verification-code
```

### Base de Datos

```sql
-- Tabla para códigos de verificación
CREATE TABLE Phone_Verification_Codes (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    phone_number VARCHAR(20) NOT NULL,
    verification_code VARCHAR(6) NOT NULL,
    expires_at DATETIME NOT NULL,
    verified TINYINT(1) DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES Users(user_id)
);

-- Campo de teléfono en usuarios
ALTER TABLE Users ADD COLUMN telefono VARCHAR(20) DEFAULT NULL;
```

### Código del Controlador

```php
// app/controllers/AuthController.php

/**
 * Enviar código de verificación por WhatsApp
 */
public function sendPhoneVerificationCode() {
    // Validar sesión de verificación pendiente
    $userId = $_SESSION['pending_phone_verification_user_id'] ?? null;
    if (!$userId) {
        Utils::jsonResponse(['success' => false, 'message' => 'Sesión no válida'], 401);
        return;
    }
    
    // Limpiar y validar número (10 dígitos México)
    $phoneNumber = preg_replace('/[^0-9]/', '', $_POST['phone_number'] ?? '');
    if (strlen($phoneNumber) !== 10) {
        Utils::jsonResponse(['success' => false, 'message' => 'Número inválido'], 400);
        return;
    }
    
    // Generar código de 6 dígitos
    $verificationCode = str_pad(random_int(0, 999999), 6, '0', STR_PAD_LEFT);
    
    // Guardar en BD (expira en 10 minutos)
    $db = Database::getConnection();
    $stmt = $db->prepare("DELETE FROM Phone_Verification_Codes WHERE user_id = ?");
    $stmt->execute([$userId]);
    
    $stmt = $db->prepare("
        INSERT INTO Phone_Verification_Codes (user_id, phone_number, verification_code, expires_at)
        VALUES (?, ?, ?, DATE_ADD(NOW(), INTERVAL 10 MINUTE))
    ");
    $stmt->execute([$userId, $phoneNumber, $verificationCode]);
    
    // Enviar por WhatsApp
    $notificationService = new NotificationService();
    $userName = $_SESSION['pending_phone_verification_name'] ?? 'Usuario';
    $sent = $notificationService->sendVerificationCode($phoneNumber, $userName, $verificationCode);
    
    if ($sent) {
        $_SESSION['pending_phone_number'] = $phoneNumber;
        Utils::jsonResponse(['success' => true, 'message' => 'Código enviado']);
    } else {
        Utils::jsonResponse(['success' => false, 'message' => 'Error al enviar'], 500);
    }
}

/**
 * Verificar código y completar login
 */
public function verifyPhoneCode() {
    $userId = $_SESSION['pending_phone_verification_user_id'] ?? null;
    $code = preg_replace('/[^0-9]/', '', $_POST['verification_code'] ?? '');
    
    $db = Database::getConnection();
    
    // Buscar código válido
    $stmt = $db->prepare("
        SELECT * FROM Phone_Verification_Codes 
        WHERE user_id = ? AND verification_code = ? AND expires_at > NOW() AND verified = 0
    ");
    $stmt->execute([$userId, $code]);
    $verification = $stmt->fetch();
    
    if (!$verification) {
        Utils::jsonResponse(['success' => false, 'message' => 'Código inválido'], 400);
        return;
    }
    
    // Marcar verificado y guardar teléfono
    $stmt = $db->prepare("UPDATE Phone_Verification_Codes SET verified = 1 WHERE id = ?");
    $stmt->execute([$verification['id']]);
    
    $stmt = $db->prepare("UPDATE Users SET telefono = ? WHERE user_id = ?");
    $stmt->execute([$verification['phone_number'], $userId]);
    
    // Completar login
    $_SESSION['user_id'] = $userId;
    unset($_SESSION['pending_phone_verification_user_id']);
    
    Utils::jsonResponse(['success' => true, 'redirect' => 'clan_member']);
}
```

---

## 📬 Notificaciones de Tareas

### Eventos que Disparan WhatsApp

| Evento | Método | Plantilla |
|--------|--------|-----------|
| Tarea asignada | `notifyTaskAssigned()` | `alerta_polaris` |
| Subtarea asignada | `notifySubtaskAssigned()` | `alerta_polaris` |

### Código de Notificación

```php
// app/services/NotificationService.php

/**
 * Enviar mensaje de WhatsApp usando la API de Meta
 */
private function sendWhatsAppMessage($phoneNumber, $userName, $taskName, $projectName) {
    // Validar teléfono
    if (empty($phoneNumber)) {
        return false;
    }
    
    // Limpiar número (solo dígitos)
    $phoneNumber = preg_replace('/[^0-9]/', '', $phoneNumber);
    
    // Agregar código de país México si tiene 10 dígitos
    if (strlen($phoneNumber) == 10) {
        $phoneNumber = '52' . $phoneNumber;
    }
    
    // Preparar payload con plantilla alerta_polaris
    $payload = [
        'messaging_product' => 'whatsapp',
        'to' => $phoneNumber,
        'type' => 'template',
        'template' => [
            'name' => 'alerta_polaris',
            'language' => ['code' => 'en'],
            'components' => [
                [
                    'type' => 'body',
                    'parameters' => [
                        ['type' => 'text', 'text' => $userName],
                        ['type' => 'text', 'text' => $taskName],
                        ['type' => 'text', 'text' => $projectName]
                    ]
                ]
            ]
        ]
    ];
    
    // Enviar petición HTTP con cURL
    $ch = curl_init($this->whatsappApiUrl);
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode($payload),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer ' . $this->whatsappToken,
            'Content-Type: application/json'
        ],
        CURLOPT_TIMEOUT => 30
    ]);
    
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    
    return ($httpCode >= 200 && $httpCode < 300);
}

/**
 * Notificar asignación de tarea
 */
public function notifyTaskAssigned($taskId, $assignedUserIds) {
    // ... obtener info de tarea ...
    
    foreach ($users as $user) {
        // Enviar correo electrónico
        if (!empty($user['email'])) {
            $this->mailer->sendHtml($user['email'], 'Tarea asignada', $html);
        }
        
        // Enviar WhatsApp si tiene teléfono
        if (!empty($user['telefono'])) {
            $this->sendWhatsAppMessage(
                $user['telefono'],
                $user['full_name'],
                $taskInfo['task_name'],
                $taskInfo['project_name']
            );
        }
    }
}
```

---

## 🐛 Debug y Logs

El sistema incluye logs detallados para troubleshooting:

```php
error_log("=== WHATSAPP DEBUG INICIO ===");
error_log("WhatsApp: Teléfono recibido: '$phoneNumber'");
error_log("WhatsApp: Usuario: '$userName'");
error_log("WhatsApp: Tarea: '$taskName'");
error_log("WhatsApp: Proyecto: '$projectName'");
error_log("WhatsApp: Payload JSON: " . json_encode($payload));
error_log("WhatsApp: HTTP Code: $httpCode");
error_log("WhatsApp: Response: $response");
error_log("=== WHATSAPP DEBUG FIN ===");
```

### Ver logs en el servidor

```bash
# En el servidor Bitnami
sudo tail -f /opt/bitnami/apache/logs/error_log | grep WhatsApp
```

---

## 🔄 Formato de Números de Teléfono

El sistema maneja automáticamente el formato:

| Entrada | Resultado | Acción |
|---------|-----------|--------|
| `5512345678` | `525512345678` | Agrega código 52 (México) |
| `525512345678` | `525512345678` | Ya tiene código, no modifica |
| `1-551-234-5678` | `15512345678` | Limpia caracteres no numéricos |
| `55123` | **Rechazado** | Muy corto (< 10 dígitos) |

---

## 📊 Estructura de Archivos

```
app/
├── controllers/
│   └── AuthController.php          # Verificación de teléfono
├── services/
│   └── NotificationService.php     # Envío de WhatsApp
└── views/
    └── login.php                   # UI de verificación

public/
└── index.php                       # Rutas de API
```

---

## ⚠️ Consideraciones Importantes

1. **Token de acceso**: El token de Meta tiene fecha de expiración. Renovar periódicamente.

2. **Plantillas**: Las plantillas deben estar **aprobadas** en Meta Business Suite antes de usarse.

3. **Límites de envío**: La API de WhatsApp tiene límites de mensajes por día según el nivel de la cuenta.

4. **Números verificados**: Solo se pueden enviar mensajes a números que hayan interactuado previamente con el número de negocio (en modo sandbox) o a cualquier número (en producción aprobada).

5. **Código de país**: El sistema asume México (52) por defecto. Modificar si se usa en otros países.

---

## 🔗 Referencias

- [Meta WhatsApp Business API Documentation](https://developers.facebook.com/docs/whatsapp/cloud-api)
- [Template Messages Guide](https://developers.facebook.com/docs/whatsapp/cloud-api/guides/send-message-templates)
- [Graph API Reference](https://developers.facebook.com/docs/graph-api/reference/whats-app-business-account/)

