<?php

/**

 * Canteen Session Pass Validator

 * POST: token, session_id

 * Auth: canteen_staff_authenticated OR valid EduTrack role session

 * Rate limit: 2 req/sec/IP

 */

if (session_status() === PHP_SESSION_NONE) session_start();

header('Content-Type: application/json');



require_once '../config.php';

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



canteen_require_active();



// Auth: PIN session OR EduTrack role

$is_pin_session  = !empty($_SESSION['canteen_staff_authenticated']);

$is_role_session = !empty($_SESSION['user_id']);

if (!$is_pin_session && !$is_role_session) {

    http_response_code(403);

    echo json_encode(['success' => false, 'message' => 'Not authenticated.']);

    exit;

}



// Rate limit: 2 requests / second / IP

$ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';

if (!canteen_rate_limit('canteen_validate_' . md5($ip), 2, 1)) {

    http_response_code(429);

    echo json_encode(['success' => false, 'message' => 'Rate limit exceeded. Slow down.']);

    exit;

}



$token      = trim((string)($_POST['token']      ?? ''));

$session_id = (int)($_POST['session_id'] ?? 0);



if ($token === '' || $session_id <= 0) {

    echo json_encode(['success' => false, 'code' => 'invalid_input', 'message' => 'Token and session_id required.']);

    exit;

}



$conn = getDBConnection();

if (!$conn) {

    echo json_encode(['success' => false, 'message' => 'Database error.']);

    exit;

}



$is_manual         = str_starts_with($token, '__MANUAL__');

$verify_method_col = $is_manual ? 'manual_id' : 'qr';



if ($is_manual) {

    // Manual student ID fallback — resolve student DB id then find entitlement

    $manual_code = trim(substr($token, 10));

    $lu = $conn->prepare("SELECT id FROM students WHERE student_id = ? AND status = 'active' LIMIT 1");

    $lu->bind_param('s', $manual_code);

    $lu->execute();

    $lu_row = $lu->get_result()->fetch_assoc();

    $lu->close();

    if (!$lu_row) {

        echo json_encode(['success' => false, 'code' => 'not_enrolled', 'message' => 'Student ID not found.']);

        $conn->close();

        exit;

    }

    $student_id = (int)$lu_row['id'];



    $stmt = $conn->prepare(

        "SELECT ce.id, ce.status, ce.qr_token_expires_at, ce.confirmed_at,

                cs.session_date, cs.status AS session_status, cs.session_name,

                s.first_name, s.last_name, s.class, s.student_id AS student_code,

                s.photo_path AS photo

         FROM canteen_entitlements ce

         JOIN canteen_sessions cs ON cs.id = ce.session_id

         JOIN students s          ON s.id  = ce.student_id

         WHERE ce.student_id = ? AND ce.session_id = ?

         LIMIT 1"

    );

    $stmt->bind_param('ii', $student_id, $session_id);

    $stmt->execute();

    $row = $stmt->get_result()->fetch_assoc();

    $stmt->close();

} else {

    // Step 1 — HMAC validation (rejects identity tokens and tampered values)

    $student_id = canteen_validate_session_token($token, $session_id);

    if ($student_id === false) {

        echo json_encode(['success' => false, 'code' => 'invalid_token', 'message' => 'Invalid canteen pass.']);

        $conn->close();

        exit;

    }



    // Step 2 — Find entitlement by qr_token

    $stmt = $conn->prepare(

        "SELECT ce.id, ce.status, ce.qr_token_expires_at, ce.confirmed_at,

                cs.session_date, cs.status AS session_status, cs.session_name,

                s.first_name, s.last_name, s.class, s.student_id AS student_code,

                s.photo_path AS photo

         FROM canteen_entitlements ce

         JOIN canteen_sessions cs ON cs.id = ce.session_id

         JOIN students s          ON s.id  = ce.student_id

         WHERE ce.qr_token = ? AND ce.session_id = ?

         LIMIT 1"

    );

    $stmt->bind_param('si', $token, $session_id);

    $stmt->execute();

    $row = $stmt->get_result()->fetch_assoc();

    $stmt->close();

}



if (!$row) {

    echo json_encode(['success' => false, 'code' => 'not_enrolled', 'message' => 'Not enrolled in this session.']);

    $conn->close();

    exit;

}



// Step 3 — Token expiry

if ($row['qr_token_expires_at'] !== null && strtotime($row['qr_token_expires_at']) < time()) {

    echo json_encode(['success' => false, 'code' => 'expired', 'message' => 'Canteen pass has expired.']);

    $conn->close();

    exit;

}



// Step 4 — Entitlement status

if ($row['status'] === 'confirmed') {

    $confirmed_at = $row['confirmed_at'] ? date('H:i', strtotime($row['confirmed_at'])) : '';

    echo json_encode(['success' => false, 'code' => 'already_confirmed',

        'message' => "Already confirmed at {$confirmed_at}."]);

    $conn->close();

    exit;

}

if ($row['status'] === 'cancelled') {

    echo json_encode(['success' => false, 'code' => 'cancelled', 'message' => 'This entitlement has been cancelled.']);

    $conn->close();

    exit;

}



// Step 5 — Session must be today and not cancelled

$today = date('Y-m-d');

if ($row['session_date'] !== $today) {

    echo json_encode(['success' => false, 'code' => 'wrong_date', 'message' => 'This pass is not valid today.']);

    $conn->close();

    exit;

}

if ($row['session_status'] === 'cancelled') {

    echo json_encode(['success' => false, 'code' => 'session_cancelled', 'message' => 'This session has been cancelled.']);

    $conn->close();

    exit;

}



// Step 6 — BEGIN TRANSACTION → update entitlement → insert scan record → COMMIT

$entitlement_id = (int)$row['id'];

$confirmed_now  = date('Y-m-d H:i:s');

$actor_id       = $is_role_session ? (int)$_SESSION['user_id'] : 0;



$conn->begin_transaction();

try {

    $upd = $conn->prepare(

        "UPDATE canteen_entitlements SET status = 'confirmed', confirmed_at = ?,

         verification_method = ?, confirmed_by = ? WHERE id = ? AND status = 'pending'"

    );

    $upd->bind_param('ssii', $confirmed_now, $verify_method_col, $actor_id, $entitlement_id);

    $upd->execute();

    $affected = $upd->affected_rows;

    $upd->close();



    if ($affected === 0) {

        // Race condition — another request confirmed it simultaneously

        $conn->rollback();

        echo json_encode(['success' => false, 'code' => 'already_confirmed',

            'message' => 'Already confirmed (concurrent request).']);

        $conn->close();

        exit;

    }



    $ins = $conn->prepare(

        "INSERT INTO canteen_scans

         (session_id, student_id, entitlement_id, scan_result, verification_method, scanned_by)

         VALUES (?, ?, ?, 'success', ?, ?)"

    );

    $ins->bind_param('iiisi', $session_id, $student_id, $entitlement_id, $verify_method_col, $actor_id);

    $ins->execute();

    $ins->close();



    $conn->commit();

} catch (Exception $e) {

    $conn->rollback();

    echo json_encode(['success' => false, 'message' => 'Database error: ' . $e->getMessage()]);

    $conn->close();

    exit;

}



// Step 7 — Build response

$student_name = trim($row['first_name'] . ' ' . $row['last_name']);

$photo_url    = '';

if (!empty($row['photo'])) {

    $photo_path = '../uploads/students/' . basename($row['photo']);

    $photo_url  = file_exists(__DIR__ . '/' . $photo_path) ? $photo_path : '';

}



logActivity($conn, $actor_id, 'canteen_scan_success',

    "Session #{$session_id} | Student: {$student_name} ({$row['student_code']})");



echo json_encode([

    'success'      => true,

    'code'         => 'confirmed',

    'student_id'   => $student_id,

    'student_name' => $student_name,

    'class_name'   => $row['class'],

    'student_code' => $row['student_code'],

    'photo_url'    => $photo_url,

    'session_name' => $row['session_name'],

    'confirmed_at' => $confirmed_now,

]);



$conn->close();

