<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\MainBundle\Workflow\EventSubscriber;

use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Workflow\Event\Event;

final readonly class EntityWorkflowTransitionEventSubscriber implements EventSubscriberInterface
{
    public function __construct(
        private LoggerInterface $chillLogger,
        private Security $security,
    ) {}

    public static function getSubscribedEvents(): array
    {
        return [
            'workflow.transition' => 'onTransition',
            'workflow.completed' => [
                ['markAsFinal', 2048],
            ],
        ];
    }

    public function markAsFinal(Event $event): void
    {
        // NOTE: it is not possible to move this method to the marking store, because
        // there is dependency between the Workflow definition and the MarkingStoreInterface (the workflow
        // constructor need a MarkingStoreInterface)

        if (!$event->getSubject() instanceof EntityWorkflow) {
            return;
        }

        /** @var EntityWorkflow $entityWorkflow */
        $entityWorkflow = $event->getSubject();
        $step = $entityWorkflow->getCurrentStep();

        $placeMetadata = $event->getWorkflow()->getMetadataStore()
            ->getPlaceMetadata($step->getCurrentStep());

        if (\array_key_exists('isFinal', $placeMetadata) && true === $placeMetadata['isFinal']) {
            $step->setIsFinal(true);
        }
    }

    public function onTransition(Event $event): void
    {
        if (!$event->getSubject() instanceof EntityWorkflow) {
            return;
        }

        /** @var EntityWorkflow $entityWorkflow */
        $entityWorkflow = $event->getSubject();

        $user = $this->security->getUser();

        $this->chillLogger->info('[workflow] apply transition on entityWorkflow', [
            'relatedEntityClass' => $entityWorkflow->getRelatedEntityClass(),
            'relatedEntityId' => $entityWorkflow->getRelatedEntityId(),
            'transition' => $event->getTransition()->getName(),
            'by_user' => $user instanceof User ? $user->getId() : (string) $user?->getUserIdentifier(),
            'entityWorkflow' => $entityWorkflow->getId(),
        ]);
    }
}
