<?php declare(strict_types=1);

namespace Pagerfanta\Doctrine\PHPCRODM\Tests;

use Doctrine\ODM\PHPCR\Query\Builder\QueryBuilder;
use Doctrine\ODM\PHPCR\Query\Query;
use Pagerfanta\Doctrine\PHPCRODM\QueryAdapter;
use PHPCR\Query\QueryResultInterface;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

final class QueryAdapterTest extends TestCase
{
    private MockObject&QueryBuilder $queryBuilder;

    private MockObject&Query $query;

    /**
     * @var QueryAdapter<mixed>
     */
    private QueryAdapter $adapter;

    protected function setUp(): void
    {
        $this->queryBuilder = $this->createMock(QueryBuilder::class);
        $this->query = $this->createMock(Query::class);

        $this->adapter = new QueryAdapter($this->queryBuilder);
    }

    public function testGetNbResultsShouldCreateTheQueryAndCount(): void
    {
        $this->queryBuilder->expects($this->once())
            ->method('getQuery')
            ->willReturn($this->query);

        /** @var MockObject&QueryResultInterface $queryResult */
        $queryResult = $this->createMock(QueryResultInterface::class);
        $queryResult->expects($this->once())
            ->method('getRows')
            ->willReturn(new \ArrayIterator([1, 2, 3, 4, 5, 6]));

        $this->query->expects($this->once())
            ->method('execute')
            ->willReturn($queryResult);

        $this->assertSame(6, $this->adapter->getNbResults());
    }

    public function testGetSlice(): void
    {
        $offset = 10;
        $length = 15;
        $slice = new \ArrayIterator();

        $this->query->expects($this->once())
            ->method('setMaxResults')
            ->with($length)
            ->willReturn($this->query);

        $this->query->expects($this->once())
            ->method('setFirstResult')
            ->with($offset)
            ->willReturn($this->query);

        $this->queryBuilder->expects($this->once())
            ->method('getQuery')
            ->willReturn($this->query);

        $this->query->expects($this->once())
            ->method('execute')
            ->willReturn($slice);

        $this->assertSame($slice, $this->adapter->getSlice($offset, $length));
    }
}
