<?php
/**
 * Ejemplo de endpoint PHP plano (sin framework) — kit FaceID v2.
 *
 * Recibe la foto del navegador (campo multipart `foto`, ver js/ejemplo.html) y
 * verifica que corresponde al usuario de la SESIÓN PHP. La API key vive sólo aquí,
 * en el servidor (variable de entorno FACEID_API_KEY), nunca en el HTML/JS.
 *
 * Uso:  POST /faceid/verificar.php   (multipart: foto)
 *       POST /faceid/verificar.php?accion=enrolar
 *
 * Requisitos: PHP 7.4+ con ext-curl y ext-json. Sin Composer.
 * Configura en php.ini: upload_max_filesize >= 5M y post_max_size >= 6M.
 */
declare(strict_types=1);

require_once __DIR__ . '/FaceIDClient.php';

session_start();
header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store');

const MAX_FOTO_BYTES = 5 * 1024 * 1024;

function responder(bool $ok, string $mensaje, array $extra = [], int $http = 200): void
{
    http_response_code($http);
    $cuerpo = ['isSuccess' => $ok, 'message' => $mensaje];
    if ($extra) {
        $cuerpo['aData'] = $extra;
    }
    echo json_encode($cuerpo, JSON_UNESCAPED_UNICODE);
    exit;
}

if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
    responder(false, 'Método no permitido.', [], 405);
}

// 1. Identidad: SIEMPRE de la sesión de tu sistema, nunca de lo que envía el navegador.
//    Ajusta las claves a tu login (aquí: $_SESSION['usuario'] = ['id'=>..., 'username'=>..., ...]).
$usuario = $_SESSION['usuario'] ?? null;
if (!$usuario || empty($usuario['id'])) {
    responder(false, 'Inicia sesión para continuar.', [], 401);
}

// 2. CSRF: compara el header con el token guardado en la sesión al renderizar la página
//    (imprímelo en una etiqueta meta name="csrf-token"; js/ejemplo.html lo envía en X-CSRF-TOKEN).
//    Genéralo al iniciar sesión: $_SESSION['csrf'] = bin2hex(random_bytes(32));
$csrf = $_SERVER['HTTP_X_CSRF_TOKEN'] ?? ($_SERVER['HTTP_X_CSRFTOKEN'] ?? '');
if (empty($_SESSION['csrf']) || !is_string($csrf) || !hash_equals((string)$_SESSION['csrf'], $csrf)) {
    responder(false, 'Sesión no válida. Recarga la página.', [], 403);
}

// 3. Validar la foto recibida.
$archivo = $_FILES['foto'] ?? null;
if (!$archivo || ($archivo['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK || !is_uploaded_file($archivo['tmp_name'])) {
    responder(false, 'No se recibió la foto.', [], 400);
}
if ($archivo['size'] > MAX_FOTO_BYTES) {
    responder(false, 'La foto supera 5 MB.', [], 400);
}
$tipo = function_exists('mime_content_type') ? (string)mime_content_type($archivo['tmp_name']) : 'image/jpeg';
if (!in_array($tipo, ['image/jpeg', 'image/png', 'image/webp'], true)) {
    responder(false, 'Formato de imagen no permitido.', [], 400);
}

// 4. Llamar a FaceID desde el servidor.
$apiKey = getenv('FACEID_API_KEY') ?: '';
if ($apiKey === '') {
    error_log('FACEID_API_KEY no está configurada');
    responder(false, 'El servicio de verificación no está disponible.', [], 500);
}

try {
    $faceid = new FaceIDClient($apiKey, getenv('FACEID_URL') ?: null);
    $foto = new CURLFile($archivo['tmp_name'], $tipo, 'captura.jpg');

    if (($_GET['accion'] ?? '') === 'enrolar') {
        $faceid->enrolar($foto, [
            'cod_number' => (string)$usuario['id'],     // identificador estable de TU sistema
            'username' => (string)($usuario['username'] ?? ''),
            'nombre' => (string)($usuario['nombres'] ?? ''),
            'apellido' => (string)($usuario['apellidos'] ?? ''),
            'email' => (string)($usuario['email'] ?? ''),
            'permite_actualizar' => true,
        ]);
        responder(true, 'Rostro registrado correctamente.');
    }

    $r = $faceid->verificar($foto, ['cod_number' => (string)$usuario['id']]);
    if (!empty($r['is_same_person'])) {
        // Aquí registra tu evento (asistencia, inicio de examen…). La decisión es del servidor.
        responder(true, 'Identidad verificada.', [
            'is_same_person' => true,
            'similarity_score' => $r['similarity_score'] ?? null,
        ]);
    }
    responder(false, 'El rostro no coincide.');
} catch (FaceIDException $e) {
    if ($e->status === 403) {
        // API key inválida o empresa desactivada: problema de configuración, no del usuario.
        error_log('FaceID rechazó la API key: ' . $e->getMessage());
        responder(false, 'El servicio de verificación no está disponible.');
    }
    if ($e->noCoincide) {
        responder(false, 'El rostro no coincide con el registrado. Mejora la luz y vuelve a intentar.');
    }
    responder(false, $e->getMessage());
} catch (Throwable $e) {
    error_log('Error FaceID: ' . $e->getMessage());
    responder(false, 'Error al procesar la foto. Intenta nuevamente.', [], 500);
}
