<?php

/*
 * This file is part of the VitiCore 2.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CpCreation\VitiCore\Bridge\Symfony\Bundle\ValueResolver;

use CpCreation\VitiCore\Behavior\HasTranslatable;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Attribute\AsTargetedValueResolver;
use Symfony\Component\HttpKernel\Controller\ValueResolverInterface;
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

#[AsTargetedValueResolver('translation_resolver')]
final class TranslationEntityValueResolver implements ValueResolverInterface
{
    public function __construct(
        private readonly EntityManagerInterface $em,
    ) {
    }

    public function resolve(Request $request, ArgumentMetadata $argument): iterable
    {
        $class = $argument->getType();

        if (null === $class || '' === $class || !class_exists($class)) {
            return [];
        }

        if (!is_a($class, HasTranslatable::class, true)) {
            return [];
        }

        $slug = $request->attributes->get('slug');
        if (!\is_string($slug) || '' === $slug) {
            return [];
        }

        $translationClass = $this->guessTranslationClass($class, $argument->getName());

        if (!class_exists($translationClass)) {
            throw new \LogicException(\sprintf('Translation class "%s" does not exist for entity "%s".', $translationClass, $class));
        }

        $translation = $this->em
            ->getRepository($translationClass)
            ->findOneBy(['slug' => $slug]);

        if (null === $translation) {
            throw new NotFoundHttpException();
        }

        $entity = $translation->getTranslatable();

        if (!$entity instanceof $class) {
            throw new NotFoundHttpException();
        }

        return [$entity];
    }

    private function guessTranslationClass(string $entityClass, string $argumentName): string
    {
        $short = ucfirst($argumentName);
        $suffix = '\\'.$short;

        if (str_ends_with($entityClass, $suffix)) {
            $base = mb_substr($entityClass, 0, -mb_strlen($suffix));
        } else {
            $pos = mb_strrpos($entityClass, '\\');
            $base = false !== $pos ? mb_substr($entityClass, 0, $pos) : $entityClass;
            $short = mb_substr($entityClass, false !== $pos ? $pos + 1 : 0);
        }

        return $base.'\\Translation\\'.$short.'Translation';
    }
}
