<?php

declare(strict_types=1);

/**
 * 本文件属于 DBErp 进销存系统。
 *
 * 版权所有 © 2026 北京珑大钜商科技有限公司。保留所有权利。
 *
 * 未经官方授权，不得删除、篡改或隐藏本文件中的版权声明、产品标识与来源信息。
 * 商业授权、官方更新与技术支持服务，请以珑大官方支持中心记录为准。
 *
 * @link https://support.loongdom.cn
 * @see  https://www.dberp.com.cn
 */

namespace App\Services\SupportCenter;

use App\Enums\SupportCenter\HostSystemUpdateExecutionStatus;
use App\Exceptions\SupportCenter\HostSystemUpdateExecutionException;
use App\Models\HostSystemUpdateExecution;

/**
 * 防止并发创建或并行运行多个系统更新执行任务。
 */
final class HostSystemUpdateExecutionLock
{
    public function findActiveExecution(): ?HostSystemUpdateExecution
    {
        return HostSystemUpdateExecution::query()
            ->whereIn('status', HostSystemUpdateExecutionStatus::activeValues())
            ->orderByDesc('id')
            ->lockForUpdate()
            ->first();
    }

    public function assertNoActiveExecution(): void
    {
        $active = HostSystemUpdateExecution::query()
            ->whereIn('status', HostSystemUpdateExecutionStatus::activeValues())
            ->orderByDesc('id')
            ->first();

        if ($active instanceof HostSystemUpdateExecution) {
            throw HostSystemUpdateExecutionException::activeExecutionExists((string) $active->execution_no);
        }
    }

    public function acquire(HostSystemUpdateExecution $execution, string $lockOwner): HostSystemUpdateExecution
    {
        $execution->fill([
            'locked_at' => now()->utc(),
            'lock_owner' => $lockOwner,
        ]);
        $execution->save();

        return $execution->fresh() ?? $execution;
    }

    public function release(HostSystemUpdateExecution $execution): HostSystemUpdateExecution
    {
        $execution->fill([
            'locked_at' => null,
            'lock_owner' => null,
        ]);
        $execution->save();

        return $execution->fresh() ?? $execution;
    }
}
