<?php
/**
 * Store a WebAuthn credential after successful fingerprint enrollment.
 * POST: student_id, credential_id (base64url), public_key (base64 SPKI DER), client_data_json (base64url)
 * Auth: admin / headteacher only
 */
if (session_status() === PHP_SESSION_NONE) session_start();
header('Content-Type: application/json');
header('Cache-Control: no-store');

require_once '../config.php';
require_once '../includes/canteen_helpers.php';

canteen_require_active();
canteen_require_role(['admin', 'headteacher'], true);

$student_id      = (int)($_POST['student_id']      ?? 0);
$credential_id   = trim($_POST['credential_id']    ?? '');
$public_key_b64  = trim($_POST['public_key']        ?? '');
$client_data_b64 = trim($_POST['client_data_json']  ?? '');

if (!$student_id || !$credential_id || !$public_key_b64 || !$client_data_b64) {
    echo json_encode(['success' => false, 'message' => 'Missing required fields.']);
    exit;
}

// ── Verify challenge from session ──────────────────────────────────────────
$stored_challenge = $_SESSION['webauthn_challenge']         ?? null;
$challenge_expiry = $_SESSION['webauthn_challenge_expires'] ?? 0;

// Consume immediately (single-use)
unset($_SESSION['webauthn_challenge'], $_SESSION['webauthn_challenge_expires']);

if (!$stored_challenge || time() > $challenge_expiry) {
    echo json_encode(['success' => false, 'message' => 'Challenge expired or missing. Please try again.']);
    exit;
}

// Decode and verify clientDataJSON
$client_data_raw = base64url_decode($client_data_b64);
if (!$client_data_raw) {
    echo json_encode(['success' => false, 'message' => 'Invalid client data.']);
    exit;
}

$client_data = json_decode($client_data_raw, true);
if (!$client_data) {
    echo json_encode(['success' => false, 'message' => 'Malformed client data JSON.']);
    exit;
}

if (($client_data['type'] ?? '') !== 'webauthn.create') {
    echo json_encode(['success' => false, 'message' => 'Invalid credential type.']);
    exit;
}

// Verify challenge matches
$received_challenge = $client_data['challenge'] ?? '';
if (!hash_equals($stored_challenge, $received_challenge)) {
    echo json_encode(['success' => false, 'message' => 'Challenge mismatch.']);
    exit;
}

// Verify origin
$expected_origin = (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'];
if (($client_data['origin'] ?? '') !== $expected_origin) {
    // Allow localhost variations for local dev
    $allowed = [$expected_origin, 'http://localhost', 'http://127.0.0.1'];
    if (!in_array($client_data['origin'] ?? '', $allowed, true)) {
        echo json_encode(['success' => false, 'message' => 'Origin mismatch.']);
        exit;
    }
}

// Validate public key is valid base64
if (base64_decode($public_key_b64, true) === false) {
    echo json_encode(['success' => false, 'message' => 'Invalid public key encoding.']);
    exit;
}

// ── Store credential ───────────────────────────────────────────────────────
$conn = getDBConnection();

// Verify student exists
$chk = $conn->prepare('SELECT id, first_name, last_name FROM students WHERE id = ? LIMIT 1');
$chk->bind_param('i', $student_id);
$chk->execute();
$student = $chk->get_result()->fetch_assoc();
$chk->close();

if (!$student) {
    $conn->close();
    echo json_encode(['success' => false, 'message' => 'Student not found.']);
    exit;
}

// Upsert into canteen_biometric_credentials
$now = date('Y-m-d H:i:s');
$stmt = $conn->prepare(
    'INSERT INTO canteen_biometric_credentials (student_id, credential_id, public_key, fingerprint_enrolled_at, enrolled_by)
     VALUES (?, ?, ?, ?, ?)
     ON DUPLICATE KEY UPDATE
       credential_id = VALUES(credential_id),
       public_key = VALUES(public_key),
       fingerprint_enrolled_at = VALUES(fingerprint_enrolled_at),
       enrolled_by = VALUES(enrolled_by)'
);
$enrolled_by = (int)($_SESSION['user_id'] ?? 0);
$stmt->bind_param('isssi', $student_id, $credential_id, $public_key_b64, $now, $enrolled_by);
$stmt->execute();
$stmt->close();

// Log biometric access
$log = $conn->prepare(
    'INSERT INTO canteen_biometric_access_log (student_id, accessed_by, action, method, result)
     VALUES (?, ?, "enroll", "fingerprint", "success")'
);
$log->bind_param('ii', $student_id, $enrolled_by);
$log->execute();
$log->close();

logActivity($conn, $enrolled_by, 'canteen_fingerprint_enroll',
    'Fingerprint enrolled for student #' . $student_id . ' (' . $student['first_name'] . ' ' . $student['last_name'] . ')');

$conn->close();

echo json_encode([
    'success' => true,
    'message' => 'Fingerprint enrolled for ' . $student['first_name'] . ' ' . $student['last_name'] . '.',
]);
