<?php

namespace App\Modules\Inventory\Stock\Services;

use Illuminate\Support\Facades\DB;

/**
 * MySQL GET_LOCK for idempotency key serialization (no-op on SQLite).
 */
final class InventoryStockAdvisoryLock
{
    public function runWithLock(?string $lockKey, \Closure $callback): mixed
    {
        if ($lockKey === null || DB::connection()->getDriverName() === 'sqlite') {
            return $callback();
        }

        $name = substr(hash('sha256', $lockKey), 0, 40);
        $got = DB::selectOne('SELECT GET_LOCK(?, 10) AS v', [$name]);
        if ((int) ($got->v ?? 0) !== 1) {
            throw new \RuntimeException('inventory_advisory_lock_failed');
        }
        try {
            return $callback();
        } finally {
            DB::selectOne('SELECT RELEASE_LOCK(?) AS v', [$name]);
        }
    }
}
