<?php

declare(strict_types=1);

namespace Gls\GlsPoland\PrestaShop\Checkout;

use Gls\GlsPoland\Entity\Carrier;
use Gls\GlsPoland\Entity\ShopDeliveryCarrier;
use Gls\GlsPoland\Translation\TranslatorAwareTrait;
use Gls\GlsPoland\Validator\ParcelShopId;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Constraints\GroupSequence;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\ConstraintValidatorFactory;
use Symfony\Component\Validator\ConstraintValidatorFactoryInterface;
use Symfony\Component\Validator\ConstraintValidatorInterface;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\ConstraintViolationListInterface;
use Symfony\Component\Validator\Validation;
use Symfony\Component\Validator\Validator\ValidatorInterface;

final class DeliveryOptionValidator implements DeliveryOptionValidatorInterface, ConstraintValidatorFactoryInterface
{
    use TranslatorAwareTrait;

    private $parcelShopIdValidator;
    private $validator;
    private $validatorFactory;

    public function __construct(ValidatorInterface $validator = null, ConstraintValidatorInterface $parcelShopIdValidator = null, ConstraintValidatorFactoryInterface $validatorFactory = null)
    {
        $this->validator = $validator ?? Validation::createValidatorBuilder()
            ->setConstraintValidatorFactory($this)
            ->getValidator();

        $this->parcelShopIdValidator = $parcelShopIdValidator;
        $this->validatorFactory = $validatorFactory;
    }

    public function validate(Carrier $carrier, $data): ConstraintViolationListInterface
    {
        if (!$carrier instanceof ShopDeliveryCarrier) {
            return new ConstraintViolationList();
        }

        return $this->validator->validate($data['parcel_shop_id'] ?? null, [
            new NotBlank([
                'message' => $this->getTranslator()->trans('Please select a ParcelShop.', [], 'Modules.Glspoland.Checkout'),
            ]),
            new Length([
                'max' => 20,
                'maxMessage' => $this->getTranslator()->trans('Invalid ParcelShop ID.', [], 'Modules.Glspoland.Checkout'),
            ]),
            new ParcelShopId(['groups' => 'API']),
        ], new GroupSequence([Constraint::DEFAULT_GROUP, 'API']));
    }

    public function getInstance(Constraint $constraint): ConstraintValidatorInterface
    {
        if ($constraint instanceof ParcelShopId && null !== $this->parcelShopIdValidator) {
            return $this->parcelShopIdValidator;
        }

        if (null === $this->validatorFactory) {
            $this->validatorFactory = new ConstraintValidatorFactory();
        }

        return $this->validatorFactory->getInstance($constraint);
    }
}
