<?php

namespace AutoAdmin\Bundle\Content\Doctrine\EventListener;

use AutoAdmin\Bundle\Content\Model\NameInterface;
use AutoAdmin\Bundle\Content\Model\SlugInterface;
use AutoAdmin\Bundle\Content\Model\TitleInterface;
use AutoAdmin\Bundle\Content\Model\TranslatableInterface;
use AutoAdmin\Bundle\Core\Doctrine\Traits\ListenerStateManagerTrait;
use AutoAdmin\Bundle\Core\Slugger\Slugger;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Event\PrePersistEventArgs;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\Events;

class SlugSubscriber implements EventSubscriber
{
    use ListenerStateManagerTrait;

    private EntityManagerInterface $entityManager;
    private ?EntityRepository $repository = null;

    public function __construct(
        private readonly Slugger $slugger
    ) {}

    public function getSubscribedEvents(): array
    {
        return [
            Events::prePersist,
            Events::preUpdate,
        ];
    }

    public function prePersist(PrePersistEventArgs $args): void
    {
        if (!$this->canRun()) {
            return;
        }
        $this->handleSlugLogic($args->getObjectManager(), $args->getObject());
    }

    public function preUpdate(PreUpdateEventArgs $args): void
    {
        if (!$this->canRun()) {
            return;
        }
        $this->handleSlugLogic($args->getObjectManager(), $args->getObject());
    }

    private function handleSlugLogic(EntityManagerInterface $entityManager, object $entity): void
    {
        $this->entityManager = $entityManager;

        if ($entity instanceof SlugInterface) {
            $this->generateSlug($entity);
        }

        if ($entity instanceof TranslatableInterface) {
            $this->processTranslations($entity);
        }
    }

    private function generateSlug(SlugInterface $entity): void
    {
        if (
            empty($entity->getSlug())
            || (empty($entity->getId()) && !empty($entity->getSlug()))
        ) {
            $slugInput = $this->getSlugInput($entity);

            if ($slugInput !== null) {
                $entity->setSlug($this->slugger->slugify($slugInput));
            }
        }
    }

    private function getSlugInput(SlugInterface $entity): ?string
    {
        if ($entity instanceof NameInterface) {
            return $entity->getName();
        }

        if ($entity instanceof TitleInterface) {
            return $entity->getTitle();
        }

        return null;
    }

    private function processTranslations(TranslatableInterface $entity): void
    {
        $this->repository = $this->entityManager->getRepository($entity::class);

        if ($translation = $entity->getCurrentTranslation()) {
            $this->handleSlugLogic($this->entityManager, $translation);
        }
    }
}
