<?php
declare(strict_types=1);

ini_set('display_errors', '0');
ini_set('log_errors', '1');
ini_set('error_log', __DIR__ . '/php_errors.log');
error_reporting(E_ALL);

session_start();

if (!isset($_SESSION['user_id'])) {
    $_SESSION['user_id'] = bin2hex(random_bytes(16));
}

$userId    = (string) $_SESSION['user_id'];
$sessionId = session_id();

$LOCK_FILE = __DIR__ . '/lock.json';
$TIMEOUT   = 15; // s
$GRACE     = 5;  // s

header('Content-Type: application/json; charset=utf-8');

function read_lock(string $path): ?array {
    if (!file_exists($path)) return null;
    $fp = fopen($path, 'r');
    if (!$fp) return null;
    try {
        if (flock($fp, LOCK_SH)) {
            $raw = stream_get_contents($fp);
            flock($fp, LOCK_UN);
            $data = json_decode($raw, true);
            return is_array($data) ? $data : null;
        }
    } finally {
        fclose($fp);
    }
    return null;
}

function is_expired(?array $lock, int $timeout, int $grace): bool {
    if (!$lock || !isset($lock['timestamp'])) return true;
    $now = time();
    $diff = $now - (int)$lock['timestamp'];
    return $diff > ($timeout + $grace);
}

function is_mine(?array $lock, string $userId, string $sessionId): bool {
    if (!$lock) return false;
    return isset($lock['user_id'], $lock['session_id'])
        && $lock['user_id'] === $userId
        && $lock['session_id'] === $sessionId;
}

$lock    = read_lock($LOCK_FILE);
$expired = is_expired($lock, $TIMEOUT, $GRACE);
$mine    = is_mine($lock, $userId, $sessionId);

$response = [
    'ok'        => true,
    'now'       => time(),
    'config'    => ['timeout' => $TIMEOUT, 'grace' => $GRACE],
    'hasLock'   => (bool)$lock,
    'isLocked'  => !$expired && (bool)$lock,
    'expired'   => $expired,
    'mine'      => $mine,
    'owner'     => $lock['user_id'] ?? null,
    'lock'      => $lock
];

echo json_encode($response, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
