<?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\Validator;

use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Workflow\EntityWorkflowManager;
use Chill\MainBundle\Workflow\Exception\HandlerNotFoundException;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException;
use Symfony\Component\Workflow\WorkflowInterface;

class EntityWorkflowCreationValidator extends \Symfony\Component\Validator\ConstraintValidator
{
    public function __construct(private readonly EntityWorkflowManager $entityWorkflowManager) {}

    /**
     * @param EntityWorkflow $value
     */
    public function validate($value, Constraint $constraint)
    {
        if (!$value instanceof EntityWorkflow) {
            throw new UnexpectedValueException($value, EntityWorkflow::class);
        }

        if (!$constraint instanceof EntityWorkflowCreation) {
            throw new UnexpectedTypeException($constraint, EntityWorkflowCreation::class);
        }

        try {
            $handler = $this->entityWorkflowManager->getHandler($value);
        } catch (HandlerNotFoundException) {
            $this->context->buildViolation($constraint->messageHandlerNotFound)
                ->addViolation();

            return;
        }

        if (null === $handler->getRelatedEntity($value)) {
            $this->context->buildViolation($constraint->messageEntityNotFound)
                ->addViolation();
        }

        $workflows = $this->entityWorkflowManager->getSupportedWorkflows($value);

        $matched = array_filter($workflows, static fn (WorkflowInterface $workflow) => $workflow->getName() === $value->getWorkflowName());

        if (0 === \count($matched)) {
            $this->context->buildViolation($constraint->messageWorkflowNotAvailable)
                ->addViolation();
        }
    }
}
