<?php
/**
 * Verificación de la identidad por BSUID (nombres de usuario de WhatsApp).
 * Ejecutar: php test_bsuid.php
 */
require_once __DIR__ . '/../services/WhatsAppService.php';

$fallos = 0;
function chequear($descripcion, $condicion) {
    global $fallos;
    if ($condicion) { echo "  ok    $descripcion\n"; }
    else { echo "  FALLA $descripcion\n"; $fallos++; }
}

// --- 1. Reconocer un BSUID y no confundirlo con un teléfono ---
chequear('reconoce el BSUID real de hoy',   WhatsAppService::esBsuid('CO.1761088155094242'));
chequear('reconoce el BSUID largo de Meta', WhatsAppService::esBsuid('US.13491208655302741918'));
chequear('un celular NO es BSUID',          !WhatsAppService::esBsuid('573214533764'));
chequear('vacío NO es BSUID',               !WhatsAppService::esBsuid(''));
chequear('texto suelto NO es BSUID',        !WhatsAppService::esBsuid('CO.abc'));

// --- 2. formatPhoneNumber no debe destrozar el BSUID ---
$svc = (new ReflectionClass('WhatsAppService'))->newInstanceWithoutConstructor();
$fmt = new ReflectionMethod('WhatsAppService', 'formatPhoneNumber');
$fmt->setAccessible(true);

chequear('el BSUID sale intacto',
    $fmt->invoke($svc, 'CO.1761088155094242') === 'CO.1761088155094242');
chequear('el celular sin indicativo sigue recibiendo el 57',
    $fmt->invoke($svc, '3214533764') === '573214533764');
chequear('el celular con indicativo se conserva',
    $fmt->invoke($svc, '573214533764') === '573214533764');

// --- 3. El payload debe usar `recipient` para BSUID y `to` para teléfonos ---
// Se replica la transformación de sendMessage(), que es privada y hace red.
$transformar = function (array $payload) {
    if (isset($payload['to']) && WhatsAppService::esBsuid($payload['to'])) {
        $payload['recipient'] = $payload['to'];
        unset($payload['to']);
    }
    return $payload;
};

$conBsuid = $transformar(['to' => 'CO.1761088155094242', 'type' => 'text']);
chequear('con BSUID se envía en `recipient`', ($conBsuid['recipient'] ?? null) === 'CO.1761088155094242');
chequear('con BSUID desaparece `to`',         !isset($conBsuid['to']));

$conTel = $transformar(['to' => '573214533764', 'type' => 'text']);
chequear('con teléfono se mantiene `to`',      ($conTel['to'] ?? null) === '573214533764');
chequear('con teléfono no aparece `recipient`', !isset($conTel['recipient']));

// --- 4. El webhook debe extraer el remitente del payload real que llegó hoy ---
$payloadReal = json_decode('{"messaging_product":"whatsapp",
  "contacts":[{"profile":{"name":"con la fe puesta en Dios","username":"Luzmarytosfer"},
               "user_id":"CO.1761088155094242"}],
  "messages":[{"from_user_id":"CO.1761088155094242","id":"wamid.XXX",
               "timestamp":"1786481656","text":{"body":"Buenos dias"},"type":"text"}]}', true);

$m = $payloadReal['messages'][0];
$remitente = $m['from'] ?? ($m['wa_id'] ?? ($m['from_user_id'] ?? null));
chequear('el mensaje que se perdía ahora sí tiene remitente', $remitente === 'CO.1761088155094242');

$nombres = [];
foreach ($payloadReal['contacts'] as $c) {
    $n = $c['profile']['name'] ?? null;
    if (!$n) continue;
    foreach ([$c['wa_id'] ?? null, $c['user_id'] ?? null] as $k) {
        if ($k) $nombres[$k] = $n;
    }
}
chequear('se rescata el nombre aunque no haya wa_id',
    ($nombres['CO.1761088155094242'] ?? null) === 'con la fe puesta en Dios');

// --- 5. El identificador debe caber en la columna ---
chequear('el BSUID más largo cabe en varchar(32)', strlen('US.13491208655302741918') <= 32);

// --- 6. Extraer el teléfono del contacto compartido (webhook `contacts` de Meta) ---
$extraerTelefono = function (array $mensaje) {
    foreach ($mensaje['contacts'] ?? [] as $c) {
        foreach ($c['phones'] ?? [] as $t) {
            $cand = $t['wa_id'] ?? ($t['phone'] ?? null);
            if ($cand) return preg_replace('/[^0-9]/', '', $cand);
        }
    }
    return null;
};

$porBoton = ['type' => 'contacts', 'from_user_id' => 'CO.1761088155094242',
    'contacts' => [['origin' => 'contact_request',
        'phones' => [['phone' => '+57 321 4533764', 'wa_id' => '573214533764', 'type' => 'CELL']]]]];
chequear('del botón se extrae el teléfono', $extraerTelefono($porBoton) === '573214533764');

// Compartido a mano: puede venir con vcard y sin wa_id
$aMano = ['type' => 'contacts', 'from_user_id' => 'CO.1761088155094242',
    'contacts' => [['origin' => 'other', 'vcard' => 'BEGIN:VCARD...',
        'phones' => [['phone' => '+57 321 453 3764', 'type' => 'CELL']]]]];
chequear('compartido a mano también se extrae', $extraerTelefono($aMano) === '573214533764');
chequear('sin teléfono devuelve nulo', $extraerTelefono(['type' => 'contacts', 'contacts' => [[]]]) === null);

// --- 7. El botón para pedir el contacto debe armarse como exige Meta ---
$pedir = new ReflectionMethod('WhatsAppService', 'pedirContacto');
chequear('pedirContacto existe y es pública', $pedir->isPublic());

$payloadBoton = [
    'messaging_product' => 'whatsapp',
    'recipient_type'    => 'individual',
    'to'                => $fmt->invoke($svc, 'CO.1761088155094242'),
    'type'              => 'interactive',
    'interactive'       => ['type' => 'request_contact_info',
                            'body' => ['text' => 'texto'],
                            'action' => ['name' => 'request_contact_info']],
];
$enviado = $transformar($payloadBoton);
chequear('el botón viaja con `recipient` cuando es BSUID',
    ($enviado['recipient'] ?? null) === 'CO.1761088155094242' && !isset($enviado['to']));
chequear('el tipo interactivo es el que Meta espera',
    $enviado['interactive']['type'] === 'request_contact_info'
    && $enviado['interactive']['action']['name'] === 'request_contact_info');

// --- 8. La ficha del paciente no debe recibir el BSUID como teléfono ---
// Réplica de la decisión de Paciente::obtenerOCrearDesdeWhatsapp()
$fichaDesde = function ($phoneNumber, $nombre = null) {
    $sinTelefono = esBsuid($phoneNumber);
    return [
        'nombre_completo' => $nombre ?? ($sinTelefono ? 'Paciente sin identificar' : 'Paciente ' . $phoneNumber),
        'telefono'        => $sinTelefono ? null : $phoneNumber,
    ];
};

$fichaOculta = $fichaDesde('CO.1761088155094242');
chequear('la ficha queda SIN teléfono si es BSUID',   $fichaOculta['telefono'] === null);
chequear('y sin el identificador metido en el nombre',
    strpos($fichaOculta['nombre_completo'], 'CO.') === false);

$fichaNormal = $fichaDesde('573214533764');
chequear('con teléfono real la ficha lo conserva',    $fichaNormal['telefono'] === '573214533764');
chequear('y el nombre por defecto no cambia',         $fichaNormal['nombre_completo'] === 'Paciente 573214533764');

// El daño concreto que se evita: normalizarTelefono() dejaba 16 dígitos con
// toda la pinta de un número real dentro de la historia clínica.
$comoQuedaba = preg_replace('/[^0-9+]/', '', 'CO.1761088155094242');
chequear('antes se guardaba un número falso creíble', $comoQuedaba === '1761088155094242');
chequear('y ahora eso ya no llega al campo teléfono', $fichaOculta['telefono'] !== $comoQuedaba);

// --- 9. Solo se pide el contacto a quien hace falta, y una sola vez ---
$decidir = function ($phoneNumber, $pedidoAt) {
    if (!esBsuid($phoneNumber)) return 'no_hace_falta';
    if (!empty($pedidoAt))      return 'ya_se_pidio';
    return 'pedido';
};
chequear('a quien tiene teléfono no se le pide',  $decidir('573214533764', null) === 'no_hace_falta');
chequear('a quien lo oculta sí se le pide',       $decidir('CO.1761088155094242', null) === 'pedido');
chequear('y no se le insiste una segunda vez',
    $decidir('CO.1761088155094242', '2026-08-11 16:00:00') === 'ya_se_pidio');

// --- 10. La comprobación vive en un solo sitio ---
chequear('esBsuid() global y el del servicio coinciden',
    esBsuid('CO.1761088155094242') === WhatsAppService::esBsuid('CO.1761088155094242')
    && esBsuid('573214533764') === WhatsAppService::esBsuid('573214533764'));

echo $fallos === 0 ? "\nTodo correcto.\n" : "\n$fallos verificaciones fallaron.\n";
exit($fallos === 0 ? 0 : 1);
