<?php
declare(strict_types=1);

namespace App\Validator\Core;

use App\Enum\Core\ContactPointTypeEnum;
use App\Repository\Core\ContactPointRepository;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use App\Entity\Core\ContactPoint;

/**
 * Classe control qu'une seul et même type de point de contact est autorisé pour chaque owner (organization, person, place)
 */
class ContactPointValidator extends ConstraintValidator
{
    public function __construct(private readonly ContactPointRepository $contactPointRepository){}

    public function validate(mixed $value, Constraint $constraint): bool
    {
        /** @var ContactPoint $contactPoint */
        $contactPoint = $value;

        // si le type est autre, on valide
        if($contactPoint->getContactType() === ContactPointTypeEnum::OTHER()->getValue()) {
            return true;
        }

        $contactPointByType = [];
        if(!$contactPoint->getOrganization()->isEmpty()) {
            $contactPointByType = $this->contactPointRepository->getByTypeAndOrganization($contactPoint->getContactType(), $contactPoint->getOrganization()->first());
        }
        else if(!$contactPoint->getPerson()->isEmpty()) {
            $contactPointByType = $this->contactPointRepository->getByTypeAndPerson($contactPoint->getContactType(), $contactPoint->getPerson()->first());
        }

        //Si le nombre de point de contact du type est supérieur à 1, OU si le nombre est égale a 1 ET que l'id du point de contact n'est pas celui en cours : invalide.
        if(count($contactPointByType) > 1 || (count($contactPointByType) === 1 && $contactPointByType[0]->getId() !== $contactPoint->getId())){
            $this->context->buildViolation($constraint->payload)
                ->setParameter('{{ type }}', $contactPoint->getContactType())
                ->atPath('contactType')
                ->addViolation();
            return false;
        }

        return true;
    }
}