<?php

declare(strict_types=1);

namespace Dedi\SyliusTheme\Validator\Constraints;

use InvalidArgumentException;
use Sylius\Bundle\AddressingBundle\Validator\Constraints\ProvinceAddressConstraint;
use Sylius\Bundle\AddressingBundle\Validator\Constraints\ProvinceAddressConstraintValidator as BaseProvinceAddressConstraintValidator;
use Sylius\Component\Addressing\Model\AddressInterface;
use Sylius\Component\Resource\Repository\RepositoryInterface;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormError;
use Symfony\Component\Validator\Constraint;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
 * Copy of Sylius\Bundle\AddressingBundle\Validator\Constraints\ProvinceAddressConstraintValidator except it adds
 * the province error on the province field instead of the address.
 */
class ProvinceAddressConstraintValidator extends BaseProvinceAddressConstraintValidator
{
    private readonly TranslatorInterface $translator;

    public function __construct(
        RepositoryInterface $countryRepository,
        RepositoryInterface $provinceRepository,
        TranslatorInterface $translator,
    ) {
        parent::__construct(
            $countryRepository,
            $provinceRepository,
        );

        $this->translator = $translator;
    }

    public function validate($value, Constraint $constraint): void
    {
        if (!$value instanceof AddressInterface) {
            throw new InvalidArgumentException(
                'ProvinceAddressConstraintValidator can only validate instances of "Sylius\Component\Addressing\Model\AddressInterface"',
            );
        }

        if (!($constraint instanceof ProvinceAddressConstraint)) {
            throw new InvalidArgumentException(
                sprintf('Expected an instance of %s. Got: %s', ProvinceAddressConstraint::class, \get_class($constraint)),
            );
        }

        $propertyPath = $this->context->getPropertyPath();

        foreach (iterator_to_array($this->context->getViolations()) as $violation) {
            if (0 === strpos($violation->getPropertyPath(), $propertyPath)) {
                return;
            }
        }

        if (!$this->isProvinceValid($value)) {
            // custom part
            /** @var Form $rootForm */
            $rootForm = $this->context->getRoot();
            $addressForm = $rootForm->get(ltrim($propertyPath, 'data.'));

            $addressForm->get('provinceCode')->addError(new FormError(
                $this->translator->trans($constraint->message, [], 'validators'),
            ));
        }
    }
}
