<?php declare(strict_types=1);

namespace Newland\Toubiz\Sync\Neos\Domain\Repository;

use Doctrine\ORM\QueryBuilder;
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Persistence\Doctrine\Repository;
use Newland\Toubiz\Sync\Neos\Command\OrphanFinder;
use Newland\Toubiz\Sync\Neos\Domain\Model\Article;
use Newland\Toubiz\Sync\Neos\Domain\Model\Event;
use Newland\Toubiz\Sync\Neos\Domain\Model\ExternalId;

/**
 * @Flow\Scope("singleton")
 */
class ExternalIdRepository extends Repository implements OrphanFinder
{
    public function findByTypeAndId(string $type, string $id): ?ExternalId
    {
        $expr = $this->entityManager->getExpressionBuilder();
        return $this->createQueryBuilder('externalId')
            ->where($expr->eq('externalId.type', ':type'))
            ->andWhere($expr->eq('externalId.id', ':id'))
            ->setParameters(compact('type', 'id'))
            ->setMaxResults(1)
            ->getQuery()
            ->execute()[0] ?? null;
    }

    public function orphanQuery(): QueryBuilder
    {
        $query = $this->createQueryBuilder('externalid');

        $entities = [
            'article' => Article::class,
        ];

        $expressions = [];
        foreach ($entities as $name => $class) {
            $subquery = $this->_em->createQueryBuilder()
                ->select('ext.Persistence_Object_Identifier')
                ->from($class, $name)
                ->leftJoin($name . '.externalIds', 'ext');

            $expressions[] = $query->expr()->notIn(
                'externalid.Persistence_Object_Identifier',
                $subquery->getDQL()
            );
        }

        $query->where($query->expr()->andX(...$expressions));
        return $query;
    }
}
