<?php

/*
 * This file is part of the Serenity package.
 *
 * (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 Serenity\SaasBundle\Doctrine\EventListener;

use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\Events;
use Serenity\CoreBundle\Saas\SerenitySaasContext;
use Serenity\CoreBundle\Shared\Feature\SerenitySaasInterface;

#[AsDoctrineListener(event: Events::onFlush)]
class SerenitySaasListener
{
    public function __invoke(OnFlushEventArgs $args): void
    {
        $entityManager = $args->getObjectManager();
        $unitOfWork = $entityManager->getUnitOfWork();
        $serenityId = SerenitySaasContext::$identifierSerenityId;

        foreach ($unitOfWork->getScheduledEntityInsertions() as $entity) {
            if ($this->hydrateSerenitySaasId($entity, $serenityId)) {
                /** @var class-string<object> $entityClass */
                $entityClass = $entity::class;
                $meta = $entityManager->getClassMetadata($entityClass);
                $unitOfWork->recomputeSingleEntityChangeSet($meta, $entity);
            }
        }

        foreach ($unitOfWork->getScheduledCollectionUpdates() as $collectionUpdate) {
            foreach ($collectionUpdate->getInsertDiff() as $entity) {
                if ($this->hydrateSerenitySaasId($entity, $serenityId)) {
                    /** @var class-string<object> $entityClass */
                    $entityClass = $entity::class;
                    $meta = $entityManager->getClassMetadata($entityClass);
                    $unitOfWork->recomputeSingleEntityChangeSet($meta, $entity);
                }
            }
        }
    }

    private function hydrateSerenitySaasId(object $entity, ?string $serenityId = null): bool
    {
        if ($entity instanceof SerenitySaasInterface && !$entity->getSaasIdentifier() && $entity->isSaasIdentifierAutoGenerated()) {
            $entity->setSaasIdentifier($serenityId);

            return true;
        }

        return false;
    }
}
