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

use Chill\PersonBundle\Entity\Identifier\IdentifierPresenceEnum;
use Chill\PersonBundle\Entity\Identifier\PersonIdentifier;
use Chill\PersonBundle\PersonIdentifier\PersonIdentifierManagerInterface;
use Doctrine\Common\Collections\Collection;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException;

final class RequiredIdentifierConstraintValidator extends ConstraintValidator
{
    public function __construct(private readonly PersonIdentifierManagerInterface $identifierManager) {}

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

        if (!$value instanceof Collection) {
            throw new UnexpectedValueException($value, Collection::class);
        }

        foreach ($this->identifierManager->getWorkers() as $worker) {
            if (IdentifierPresenceEnum::REQUIRED !== $worker->getDefinition()->getPresence()) {
                continue;
            }

            $identifier = $value->findFirst(fn (int $key, PersonIdentifier $identifier) => $identifier->getDefinition() === $worker->getDefinition());

            if (null === $identifier || $worker->isEmpty($identifier)) {
                $this->context->buildViolation($constraint->message)
                    ->setParameter('{{ value }}', $worker->renderAsString($identifier))
                    ->setParameter('definition_id', (string) $worker->getDefinition()->getId())
                    ->setCode('c08b7b32-947f-11f0-8608-9b8560e9bf05')
                    ->addViolation();
            }
        }
    }
}
