<?php

declare(strict_types=1);

$root = getenv('POC_APP_ROOT');
$password = getenv('POC_PASSWORD');
if (!$root || !$password) exit(2);
define('APP_PATH', $root . '/application/');
require $root . '/thinkphp/base.php';
require $root . '/application/cores/database/Dm.php';
require __DIR__ . '/AdvisoryLock.php';
if (!function_exists('config')) {
    function config($name = '', $value = null, $range = '')
    {
        return $value === null ? \think\Config::get($name) : \think\Config::set($name, $value, $range);
    }
}

\think\Config::set([
    'type' => \app\cores\database\Dm::class,
    'hostname' => '127.0.0.1',
    'hostport' => 5237,
    'database' => 'ZHCT_APP',
    'username' => 'ZHCT_APP',
    'password' => $password,
    'prefix' => 'ydy_',
], 'database');

$class = new ReflectionClass(\app\common\service\database\AdvisoryLock::class);
$idMethod = $class->getMethod('lockId');
$idMethod->setAccessible(true);
$name = 'codex:framework-lock:' . bin2hex(random_bytes(4));
$id = $idMethod->invoke(null, $name);
$second = new PDO('dm:host=127.0.0.1;port=5237;schema=ZHCT_APP', 'ZHCT_APP', $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
$acquired = false;
try {
    $acquired = \app\common\service\database\AdvisoryLock::acquire($name, 0);
    if (!$acquired) throw new RuntimeException('Framework failed to acquire DM lock');
    $request = $second->prepare('SELECT DBMS_LOCK.REQUEST(?,6,0) FROM DUAL');
    $request->execute([$id]);
    if ((int)$request->fetchColumn() !== 1) throw new RuntimeException('Competing session was not busy');
    \app\common\service\database\AdvisoryLock::release($name);
    $acquired = false;
    $request->execute([$id]);
    if ((int)$request->fetchColumn() !== 0) throw new RuntimeException('Competing session could not acquire released lock');
    $release = $second->prepare('SELECT DBMS_LOCK.RELEASE(?) FROM DUAL');
    $release->execute([$id]);
    if ((int)$release->fetchColumn() !== 0) throw new RuntimeException('Competing session could not release lock');
    echo json_encode(['framework_lock' => 'passed', 'competing_session' => 'busy_then_acquired']) . PHP_EOL;
} finally {
    if ($acquired) \app\common\service\database\AdvisoryLock::release($name);
}
