<?php
// api/checkin.php
// GET  → public QR tap: shows ticket confirmation only (NO check-in)
// POST → checker station only: performs real check-in with checker ID
require_once __DIR__ . '/../config.php';
startSecureSession();

$isPost = $_SERVER['REQUEST_METHOD'] === 'POST';

if ($isPost) {
    // Must come from an authenticated checker session or include valid checker_id
    $body      = json_decode(file_get_contents('php://input'), true) ?? [];
    $token     = trim($body['token']      ?? '');
    $guestId   = (int)($body['guest_id']  ?? 0);
    $method    = in_array($body['method'] ?? '', ['qr','manual']) ? $body['method'] : 'qr';
    $checkerId = (int)($body['checker_id'] ?? 0);
    $eventId   = (int)($body['event_id']  ?? 0);
    $action    = $body['action'] ?? 'check_in';

    // CSRF: token arrives in the JSON body (or X-CSRF-Token header)
    if (!csrfValid($body['csrf_token'] ?? null)) {
        jsonOut(['success'=>false, 'message'=>'Invalid or expired security token. Please reload the scanner.'], 403);
    }

    // Verify checker session matches
    if (!$checkerId || empty($_SESSION['checker_id']) || (int)$_SESSION['checker_id'] !== $checkerId) {
        jsonOut(['success'=>false, 'message'=>'Unauthorised. Please log in as a checker.'], 401);
    }
} else {
    // GET: guest tapped their QR link — confirm ticket only, no check-in
    $token     = trim($_GET['token'] ?? '');
    $method    = 'qr';
    $checkerId = 0;
    $eventId   = 0;
    $guestId   = 0;
    $action    = 'confirm'; // new action — ticket confirmation only
}

$db = db();

// ── Undo check-in (checker only) ─────────────────────────────
if ($action === 'undo') {
    $stmt = $db->prepare('SELECT g.*, e.single_use_tokens FROM guests g
                          JOIN events e ON e.id=g.event_id WHERE g.id=?');
    $stmt->execute([$guestId]);
    $guest = $stmt->fetch();
    if ($guest && (int)$guest['single_use_tokens'] === 1) {
        jsonOut(['success'=>false, 'message'=>'Single-use mode is on for this event — check-ins cannot be undone.'], 403);
    }
    if ($guest && $guest['checked_in']) {
        $db->prepare('UPDATE guests SET checked_in=0,check_in_time=NULL,check_in_method=NULL,checked_by=NULL WHERE id=?')
           ->execute([$guestId]);
        $db->prepare('INSERT INTO checkin_log (guest_id,event_id,checker_id,method,action) VALUES (?,?,?,?,?)')
           ->execute([$guestId, $guest['event_id'], $checkerId ?: null, $method, 'undo']);
        jsonOut(['success'=>true, 'action'=>'undo']);
    }
    jsonOut(['success'=>false, 'message'=>'Guest not found or not checked in.'], 404);
}

// ── Walk-in: create a guest on the spot and check them in ─────
if ($action === 'walkin') {
    $name = trim($body['name'] ?? '');
    $cat  = trim($body['category'] ?? '') ?: null;
    // Trust the checker's own event, not client-supplied event_id
    $wEvent = (int)($_SESSION['checker_event'] ?? 0);
    if (!$wEvent) jsonOut(['success'=>false, 'message'=>'No event in session.'], 400);
    if ($name === '') jsonOut(['success'=>false, 'message'=>'Name is required.'], 400);

    // Respect check-in window if configured
    $evRow = $db->prepare('SELECT checkin_opens_at, checkin_closes_at, webhook_url FROM events WHERE id=?');
    $evRow->execute([$wEvent]);
    $ev  = $evRow->fetch() ?: [];
    $now = time();
    if (!empty($ev['checkin_opens_at'])  && $now < strtotime($ev['checkin_opens_at']))  jsonOut(['success'=>false,'blocked'=>true,'message'=>'Check-in has not opened yet.'], 403);
    if (!empty($ev['checkin_closes_at']) && $now > strtotime($ev['checkin_closes_at'])) jsonOut(['success'=>false,'blocked'=>true,'message'=>'Check-in has closed.'], 403);

    $tok = generateToken();
    $db->prepare('INSERT INTO guests (event_id,name,category,token,checked_in,check_in_time,check_in_method,checked_by)
                  VALUES (?,?,?,?,1,NOW(),?,?)')
       ->execute([$wEvent, $name, $cat, $tok, 'manual', $checkerId]);
    $newId = (int)$db->lastInsertId();
    $db->prepare('INSERT INTO checkin_log (guest_id,event_id,checker_id,method,action) VALUES (?,?,?,?,?)')
       ->execute([$newId, $wEvent, $checkerId, 'manual', 'check_in']);

    if (!empty($ev['webhook_url'])) {
        fireWebhook($ev['webhook_url'], [
            'event'=>'guest.checked_in', 'walkin'=>true, 'event_id'=>$wEvent,
            'guest_id'=>$newId, 'name'=>$name, 'category'=>$cat, 'method'=>'manual',
            'checker_id'=>$checkerId, 'time'=>date('c'),
        ]);
    }
    jsonOut(['success'=>true, 'method'=>'manual', 'walkin'=>true,
             'guest'=>['id'=>$newId, 'name'=>$name, 'category'=>$cat]]);
}

// ── Resolve guest ─────────────────────────────────────────────
if ($token) {
    $stmt = $db->prepare('SELECT g.*, e.title event_title, e.event_date, e.venue, e.slug,
                                 e.single_use_tokens, e.checkin_opens_at, e.checkin_closes_at, e.webhook_url
                          FROM guests g JOIN events e ON e.id=g.event_id WHERE g.token=?');
    $stmt->execute([$token]);
} elseif ($guestId) {
    $stmt = $db->prepare('SELECT g.*, e.title event_title, e.event_date, e.venue, e.slug,
                                 e.single_use_tokens, e.checkin_opens_at, e.checkin_closes_at, e.webhook_url
                          FROM guests g JOIN events e ON e.id=g.event_id WHERE g.id=?');
    $stmt->execute([$guestId]);
} else {
    if (!$isPost) {
        header('Location: ' . BASE_URL . '/event/not_found.php'); exit;
    }
    jsonOut(['success'=>false, 'message'=>'No token or guest ID provided.'], 400);
}

$guest = $stmt->fetch();

if (!$guest) {
    if (!$isPost) {
        header('Location: ' . BASE_URL . '/event/not_found.php'); exit;
    }
    jsonOut(['success'=>false, 'message'=>'Guest not found.']);
}

// Verify event matches if provided
if ($eventId && (int)$guest['event_id'] !== $eventId) {
    jsonOut(['success'=>false, 'message'=>'Guest does not belong to this event.']);
}

// ── GET: ticket confirmation only — no check-in ───────────────
if ($action === 'confirm') {
    // Just redirect to the confirmation page showing their ticket details
    header('Location: ' . BASE_URL . '/event/confirmed.php?token=' . urlencode($guest['token']));
    exit;
}

// ── POST: real check-in by authenticated checker ──────────────
if ($guest['checked_in']) {
    // Already checked in — return info so checker can see who/when
    $checkerName = '';
    if ($guest['checked_by']) {
        $cn = $db->prepare('SELECT name FROM checkers WHERE id=?');
        $cn->execute([$guest['checked_by']]);
        $checkerName = $cn->fetchColumn() ?: '';
    }
    jsonOut([
        'success'         => false,
        'already_checked' => true,
        'guest'           => [
            'id'              => $guest['id'],
            'name'            => $guest['name'],
            'email'           => $guest['email'],
            'category'        => $guest['category'],
            'table_number'    => $guest['table_number'],
            'check_in_time'   => $guest['check_in_time'],
            'check_in_method' => $guest['check_in_method'],
            'checked_by_name' => $checkerName,
        ]
    ]);
}

// ── Check-in window enforcement (anti-replay / time-boxing) ──
$now = time();
if (!empty($guest['checkin_opens_at']) && $now < strtotime($guest['checkin_opens_at'])) {
    jsonOut(['success'=>false, 'blocked'=>true, 'message'=>'Check-in has not opened yet for this event.'], 403);
}
if (!empty($guest['checkin_closes_at']) && $now > strtotime($guest['checkin_closes_at'])) {
    jsonOut(['success'=>false, 'blocked'=>true, 'message'=>'Check-in has closed for this event.'], 403);
}

// Perform check-in — record checker
$db->prepare(
    'UPDATE guests SET checked_in=1,check_in_time=NOW(),check_in_method=?,checked_by=? WHERE id=?'
)->execute([$method, $checkerId, $guest['id']]);

$db->prepare(
    'INSERT INTO checkin_log (guest_id,event_id,checker_id,method,action) VALUES (?,?,?,?,?)'
)->execute([$guest['id'], $guest['event_id'], $checkerId, $method, 'check_in']);

// ── Fire webhook (fire-and-forget) ───────────────────────────
if (!empty($guest['webhook_url'])) {
    fireWebhook($guest['webhook_url'], [
        'event'      => 'guest.checked_in',
        'event_id'   => (int)$guest['event_id'],
        'guest_id'   => (int)$guest['id'],
        'name'       => $guest['name'],
        'category'   => $guest['category'],
        'method'     => $method,
        'checker_id' => $checkerId,
        'time'       => date('c'),
    ]);
}

jsonOut([
    'success'      => true,
    'method'       => $method,
    'checker_id'   => $checkerId,
    'guest'        => [
        'id'           => $guest['id'],
        'name'         => $guest['name'],
        'email'        => $guest['email'],
        'category'     => $guest['category'],
        'table_number' => $guest['table_number'],
        'seat_number'  => $guest['seat_number'],
    ]
]);
