<?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\User;
use Chill\MainBundle\Workflow\WorkflowTransitionContextDTO;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Workflow\Registry;

final class TransitionHasSignerIfSignatureValidator extends ConstraintValidator
{
    public function __construct(
        private readonly Registry $registry,
    ) {}

    public function validate($value, Constraint $constraint): void
    {
        if (!$constraint instanceof TransitionHasSignerIfSignature) {
            throw new UnexpectedTypeException($constraint, TransitionHasSignerIfSignature::class);
        }

        if (!$value instanceof WorkflowTransitionContextDTO) {
            throw new UnexpectedTypeException($value, WorkflowTransitionContextDTO::class);
        }

        if (null === $value->transition) {
            return;
        }

        $workflow = $this->registry->get($value->entityWorkflow, $value->entityWorkflow->getWorkflowName());

        foreach ($value->transition->getTos() as $to) {
            $metadata = $workflow->getMetadataStore()->getPlaceMetadata($to);

            if ([] !== ($metadata['isSignature'] ?? [])) {
                if (null === $value->futureUserSignature && [] === $value->futurePersonSignatures) {
                    $this->context->buildViolation($constraint->message)
                        ->setCode($constraint->code)
                        ->addViolation();

                    return;
                }

                return;

            }
        }

        // at this step, there is no signature in the To, we must check there is not users or persons
        if ($value->futureUserSignature instanceof User || [] !== $value->futurePersonSignatures) {
            $this->context->buildViolation($constraint->messageShouldBeEmpty)
                ->setCode($constraint->code)
                ->atPath($value->futureUserSignature instanceof User ? 'futureUserSignature' : 'futurePersonSignatures')
                ->addViolation();
        }
    }
}
