<?php
// customer/includes/wa_json_guard.php
// ---------------------------------------------------------------------------
// Guarantees a webauthn endpoint ALWAYS answers with JSON — never an HTML
// error page. Browsers surface HTML-instead-of-JSON as cryptic errors
// ("Unexpected token '<'" on Chrome, "The string did not match the expected
// pattern" on iOS Safari), so any warning/fatal/uncaught exception here is
// converted into a proper JSON error response instead.
// Must be required BEFORE any other include in the endpoint.
// ---------------------------------------------------------------------------

ini_set('display_errors', '0');
ini_set('log_errors', '1');
error_reporting(E_ALL);

http_response_code(200);
header('Content-Type: application/json');
header('Cache-Control: no-store');

// Swallow any stray output (warnings, BOM, whitespace from includes) so it
// can never corrupt the JSON body.
ob_start();

set_exception_handler(function ($e) {
    error_log('[webauthn] Uncaught ' . get_class($e) . ': ' . $e->getMessage() . ' @ ' . $e->getFile() . ':' . $e->getLine());
    while (ob_get_level() > 0) ob_end_clean();
    http_response_code(200);
    header('Content-Type: application/json');
    echo json_encode(['ok' => false, 'error' => 'A server error occurred. Please try again, or sign in with your password.']);
    exit;
});

register_shutdown_function(function () {
    $err = error_get_last();
    if ($err && in_array($err['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR], true)) {
        while (ob_get_level() > 0) ob_end_clean();
        if (!headers_sent()) {
            http_response_code(200);
            header('Content-Type: application/json');
        }
        echo json_encode(['ok' => false, 'error' => 'A server error occurred. Please try again, or sign in with your password.']);
        return;
    }
    // Normal path: flush buffered JSON.
    while (ob_get_level() > 0) ob_end_flush();
});
