<?php
// Verifies a passkey assertion and signs the user in.
require_once __DIR__ . '/includes/wa_json_guard.php';
session_start();
require_once __DIR__ . '/config/db.php';
require_once __DIR__ . '/includes/webauthn.php';
wa_ensure_table($conn);

$body = json_decode(file_get_contents('php://input'), true);
if (!is_array($body) || empty($body['response'])) { echo json_encode(['ok' => false, 'error' => 'bad_request']); exit; }

$credIdB64      = $body['id'] ?? '';
$clientDataJSON = wa_b64url_decode($body['response']['clientDataJSON'] ?? '');
$authData       = wa_b64url_decode($body['response']['authenticatorData'] ?? '');
$signature      = wa_b64url_decode($body['response']['signature'] ?? '');
$userHandle     = !empty($body['response']['userHandle']) ? wa_b64url_decode($body['response']['userHandle']) : '';

$chal = $_SESSION['wa_login_challenge'] ?? '';
unset($_SESSION['wa_login_challenge']);

if (!$chal || strlen($authData) < 37 || !wa_check_client_data($clientDataJSON, 'webauthn.get', $chal)) {
    echo json_encode(['ok' => false, 'error' => 'verification_failed']); exit;
}

$q = $conn->prepare(
    "SELECT wc.id, wc.user_id, wc.public_key, u.name, u.email, u.role, u.status
     FROM webauthn_credentials wc JOIN users u ON wc.user_id = u.id
     WHERE wc.credential_id = ? LIMIT 1"
);
$q->bind_param("s", $credIdB64);
$q->execute();
$cred = $q->get_result()->fetch_assoc();
if (!$cred) { echo json_encode(['ok' => false, 'error' => 'unknown_credential']); exit; }

// If a user handle was returned, it must match the credential's owner.
if ($userHandle !== '' && $userHandle !== (string)$cred['user_id']) {
    echo json_encode(['ok' => false, 'error' => 'verification_failed']); exit;
}

$rpIdHash = substr($authData, 0, 32);
$flags    = ord($authData[32]);
if (!hash_equals($rpIdHash, hash('sha256', wa_rp_id(), true))) { echo json_encode(['ok' => false, 'error' => 'rp_mismatch']); exit; }
if (!($flags & 0x01)) { echo json_encode(['ok' => false, 'error' => 'user_not_present']); exit; }
if (!wa_verify_signature($cred['public_key'], $authData, $clientDataJSON, $signature)) {
    echo json_encode(['ok' => false, 'error' => 'verification_failed']); exit;
}
if ((int)$cred['status'] !== 1) { echo json_encode(['ok' => false, 'error' => 'Your account is inactive. Please contact support.']); exit; }

// Update the stored signature counter (basic clone detection).
$newCount = unpack('N', substr($authData, 33, 4))[1];
$conn->query("UPDATE webauthn_credentials SET sign_count=" . (int)$newCount . " WHERE id=" . (int)$cred['id']);

// Sign in (a passkey is a strong factor — no separate 2FA needed).
session_regenerate_id(true);
$_SESSION['user_id']    = (int)$cred['user_id'];
$_SESSION['user_name']  = $cred['name'];
$_SESSION['user_email'] = $cred['email'];
$_SESSION['role']       = $cred['role'];
unset($_SESSION['login_error']);

setcookie('dabil_returning', '1', [
    'expires'  => time() + 60 * 60 * 24 * 365,
    'path'     => '/',
    'secure'   => !empty($_SERVER['HTTPS']),
    'httponly' => true,
    'samesite' => 'Lax',
]);

echo json_encode(['ok' => true, 'redirect' => 'dashboard.php']);
