<?php
require_once __DIR__ . '/config.php';

// Raw camera payload — contains the snapshots that parseInput() doesn't expose.
$raw       = json_decode(file_get_contents('php://input'), true) ?: [];
$cropB64   = $raw['license_plate_snapshot'] ?? '';
$fullB64   = $raw['full_snapshot']          ?? '';

$now       = date('YmdHis');
$dayname   = strtolower(date('l'));
$time      = date('Hi');
$input     = parseInput();
$plate     = $input['plate'];
$direction = $input['direction'];
$device    = $input['device'];

$log = implode(';', [$now, $plate, $direction, $device]);

if ($dayname === 'saturday' || $dayname === 'sunday') {
    writeLog('kolmen.txt', $log . ';weekend;noaction');
    die();
}

if ($time < '0700' || $time > '2000') {
    writeLog('kolmen.txt', $log . ";$dayname;outOfOfficeHours;noaction");
    die();
}

// Barrier role (entry/exit) comes from the devices table. Only meaningful for an
// approaching vehicle; deviceDirection() falls back to the legacy name heuristic
// when a camera's direction hasn't been set in Settings yet.
$role = ($direction === 'Approach') ? deviceDirection($device) : '';

if ($role === 'exit') {
    $log .= ";$dayname;$time";

    $conn        = dbConnect();
    $allowUnknown = getSetting('kolmen_allow_unknown_exit', '1') === '1';

    // Check if plate is known regardless — we always want to know
    $stmt = mysqli_prepare($conn, 'SELECT 1 FROM lp WHERE lpcontent = ? AND lplocation = 1 LIMIT 1');
    mysqli_stmt_bind_param($stmt, 's', $plate);
    mysqli_stmt_execute($stmt);
    mysqli_stmt_store_result($stmt);
    $known = mysqli_stmt_num_rows($stmt) > 0;
    mysqli_stmt_close($stmt);

    if ($known || $allowUnknown) {
        $status = $known ? 'allowed' : 'exit';
        $relay  = triggerRelay('http://10.1.1.138/leds.cgi?state=P0010&led=0');
        $log   .= $known ? ';KnownExit' : ';UnknownExit';
        $log   .= ";$relay";
    } else {
        $status = 'denied';
        $log   .= ';ExitDenied;UnknownPlate';
    }

    $ins = mysqli_prepare($conn, 'INSERT INTO logs (time, lp, device, status) VALUES (?, ?, ?, ?)');
    mysqli_stmt_bind_param($ins, 'ssss', $now, $plate, $device, $status);
    mysqli_stmt_execute($ins);
    $logid = mysqli_insert_id($conn);
    mysqli_close($conn);

    saveEventSnapshots($logid, $cropB64, $fullB64);
    writeLog('kolmen.txt', $log);
    die();
}

$log .= ";$dayname;$time";

if ($direction !== 'Approach') {
    writeLog('kolmen.txt', $log . ';no action');
    die();
}

$conn = dbConnect();
$stmt = mysqli_prepare($conn, 'SELECT 1 FROM lp WHERE lpcontent = ? AND lplocation = 1 LIMIT 1');
mysqli_stmt_bind_param($stmt, 's', $plate);
mysqli_stmt_execute($stmt);
mysqli_stmt_store_result($stmt);
$allowed = mysqli_stmt_num_rows($stmt) > 0;
mysqli_stmt_close($stmt);

$status = $allowed ? 'allowed' : 'denied';

if ($allowed) {
    $log .= ';ALLOWED';
    $log .= ';' . triggerRelay('http://10.1.1.138/leds.cgi?state=P0010&led=0');
} else {
    $log .= ';NOT allowed';
}

$ins = mysqli_prepare($conn, 'INSERT INTO logs (time, lp, device, status) VALUES (?, ?, ?, ?)');
mysqli_stmt_bind_param($ins, 'ssss', $now, $plate, $device, $status);
$ok    = mysqli_stmt_execute($ins);
$logid = $ok ? mysqli_insert_id($conn) : 0;
$log  .= $ok ? ';dbok' : ';' . mysqli_error($conn);
mysqli_stmt_close($ins);
mysqli_close($conn);

saveEventSnapshots($logid, $cropB64, $fullB64);
writeLog('kolmen.txt', $log);

/**
 * Resolve a camera's barrier role from the devices table: 'entry' or 'exit'.
 * Falls back to the legacy name convention (…UIT = exit, otherwise entry) when
 * the direction column is empty or the device is unknown, so the gate keeps
 * working even before cameras are configured in Settings.
 */
function deviceDirection(string $device): string {
    $conn = dbConnect();
    $stmt = mysqli_prepare($conn, 'SELECT direction FROM devices WHERE device_name = ? LIMIT 1');
    mysqli_stmt_bind_param($stmt, 's', $device);
    mysqli_stmt_execute($stmt);
    $row = mysqli_fetch_row(mysqli_stmt_get_result($stmt));
    mysqli_close($conn);

    $dir = $row[0] ?? null;
    if ($dir === 'entry' || $dir === 'exit') return $dir;

    return str_ends_with($device, 'UIT') ? 'exit' : 'entry';
}

/**
 * Decode the base64 JPEGs the camera POSTs and store them keyed by log id.
 * Files: admin/data/snap/<logid div 1000>/<logid>.jpg        (full frame)
 *        admin/data/snap/<logid div 1000>/<logid>_crop.jpg   (plate crop)
 * Sharded by thousands so directories stay small. Silently no-ops when a
 * snapshot field is absent ("-") or not a valid JPEG.
 */
function saveEventSnapshots(int $logid, string $cropB64, string $fullB64): void {
    if ($logid <= 0) return;
    $shard = intdiv($logid, 1000);
    $dir   = __DIR__ . "/admin/data/snap/$shard";
    if (!is_dir($dir) && !@mkdir($dir, 0775, true) && !is_dir($dir)) return;

    foreach (['' => $fullB64, '_crop' => $cropB64] as $suffix => $b64) {
        if ($b64 === '' || $b64 === '-') continue;
        $bin = base64_decode(preg_replace('/\s+/', '', $b64));
        if ($bin === false || strlen($bin) < 100) continue;
        if (substr($bin, 0, 2) !== "\xFF\xD8") continue;   // must start with JPEG SOI
        @file_put_contents("$dir/{$logid}{$suffix}.jpg", $bin);
    }
}
