<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\CoreBundle\Workflow;

/**
 * Marks an in-flight attendance withdrawal as mandated by the revocation of a
 * COMPULSORY consent.
 *
 * Such a withdrawal is a compliance action: once the precondition consent is
 * gone we may no longer process the application, so the organiser's convenience
 * guards ("no withdraw after the application deadline / grace period") must not
 * stand in the way. The legally-grounded guards — offer cancelled, offer
 * already started — still apply; see {@see AttendanceGuard}.
 *
 * The Symfony Workflow GuardEvent receives no `apply()` context, so this tiny
 * request-scoped flag is the side channel between the cascade and the guard.
 * Always toggled through {@see run()} so it is reset even on exceptions.
 */
final class CompulsoryWithdrawalContext
{
    private bool $active = false;

    public function isActive(): bool
    {
        return $this->active;
    }

    /**
     * @template T
     *
     * @param callable():T $callback
     *
     * @return T
     */
    public function run(callable $callback): mixed
    {
        $previous = $this->active;
        $this->active = true;

        try {
            return $callback();
        } finally {
            $this->active = $previous;
        }
    }
}
