<?php
namespace Newland\Toubiz\Sync\Neos\Domain\Repository;

/*
 * This file is part of the "toubiz-sync-neos" package.
 *
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
 */

use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\QueryBuilder;
use Neos\Flow\Annotations as Flow;
use Newland\Toubiz\Sync\Neos\Command\OrphanFinder;
use Newland\Toubiz\Sync\Neos\Domain\Filter\FilterInterface;
use Newland\Toubiz\Sync\Neos\Domain\Model\Medium;

/**
 * Medium repository.
 *
 * @Flow\Scope("singleton")
 *
 * @method Medium|null findOneByOriginalId(string $originalId)
 */
class MediumRepository extends AbstractRepository implements OrphanFinder
{

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

        $query->leftJoin('medium.events', 'events')
            ->leftJoin('medium.articles', 'articles')
            ->leftJoin('medium.services', 'services');

        $query->andWhere(
            $query->expr()->andX(
                $query->expr()->isNull('events.Persistence_Object_Identifier'),
                $query->expr()->isNull('articles.Persistence_Object_Identifier'),
                $query->expr()->isNull('services.Persistence_Object_Identifier')
            )
        );

        return $query;
    }

    public function countAllWithLocalResource(): int
    {
        return (int) $this->queryForMediaWithResource()
            ->select('COUNT(media.Persistence_Object_Identifier) as count')
            ->getQuery()->execute([], AbstractQuery::HYDRATE_ARRAY)[0]['count'];
    }

    public function findAllWithLocalResource(): \Generator
    {
        $iterator = $this->queryForMediaWithResource()->getQuery()->iterate();

        foreach ($iterator as $items) {
            yield from $items;
        }
    }

    private function queryForMediaWithResource(): QueryBuilder
    {
        $query = $this->createQueryBuilder('media');
        $query->where($query->expr()->isNotNull('media.resource'));
        return $query;
    }


    /**
     * @param FilterInterface $filter
     * @param QueryBuilder $query
     * @return QueryBuilder
     */
    protected function applyFilter(FilterInterface $filter, QueryBuilder $query): QueryBuilder
    {
        $this->applyBasicFilter($filter, $query);
        return $query;
    }
}
