<?php
/**
 * webauthn-register-options.php — Passkey registration: step 1
 *
 * Called from license.php-equivalent passkey management page while
 * already logged in. Generates a WebAuthn creation challenge, stores it
 * in the session for the verify step to check against, and returns the
 * options for navigator.credentials.create().
 *
 * Requires an authenticated session (include/auth.php) — registering a
 * passkey is an admin self-service action, never reachable pre-login.
 */
require_once __DIR__ . '/../includes/auth.php';

header('Content-Type: application/json; charset=UTF-8');

if (!isset($_GET['csrf_token']) || !verify_token($_GET['csrf_token'])) {
    http_response_code(403);
    echo json_encode(['success' => false, 'error' => 'Invalid request.']);
    exit;
}

$existingCredentials = $db->select('webauthn_credentials', 'credential_id', 'user_id = :uid', '', [':uid' => 1]);
$excludeIds = array_map(
    fn($row) => \lbuchs\WebAuthn\Binary\ByteBuffer::fromHex($row['credential_id']),
    $existingCredentials
);

$username = $_SESSION['name'] ?? 'admin';

try {
    $createArgs = $webAuthn->getCreateArgs(
        userId: random_bytes(16),
        userName: $username,
        userDisplayName: $username,
        requireResidentKey: false,
        requireUserVerification: 'preferred',
        excludeCredentialIds: $excludeIds
    );
} catch (\lbuchs\WebAuthn\WebAuthnException $e) {
    http_response_code(500);
    echo json_encode(['success' => false, 'error' => 'Failed to generate registration options: ' . $e->getMessage()]);
    exit;
}

// Persist the challenge for the verify step — WebAuthn challenges are
// single-use and must be checked server-side against what was actually
// issued, never trusted from the client's own response.
$_SESSION['webauthn_register_challenge'] = base64_encode($webAuthn->getChallenge()->getBinaryString());

echo json_encode(['success' => true, 'options' => $createArgs], JSON_UNESCAPED_SLASHES);
