<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\CoreBundle\Tests\Payments;

use Doctrine\ORM\Query;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder;
use Ferienpass\CoreBundle\Payments\ReceiptNumberGenerator;
use Ferienpass\CoreBundle\Repository\PaymentRepository;
use PHPUnit\Framework\TestCase;

final class ReceiptNumberGeneratorTest extends TestCase
{
    public function testGenerateWithNoPreviousReceipt(): void
    {
        $generator = $this->makeGenerator('', null);

        self::assertSame('1', $generator->generate());
    }

    public function testGenerateIncrementsExistingNumber(): void
    {
        $generator = $this->makeGenerator('', ['docNumber' => '5']);

        self::assertSame('6', $generator->generate());
    }

    public function testGenerateWithPrefix(): void
    {
        $generator = $this->makeGenerator('R-', null);

        self::assertSame('R-1', $generator->generate());
    }

    public function testGenerateWithPrefixAndExistingNumber(): void
    {
        $generator = $this->makeGenerator('R-', ['docNumber' => '42']);

        self::assertSame('R-43', $generator->generate());
    }

    public function testGenerateWithNullDocNumber(): void
    {
        $generator = $this->makeGenerator('', ['docNumber' => null]);

        self::assertSame('1', $generator->generate());
    }

    private function makeGenerator(string $prefix, ?array $queryResult): ReceiptNumberGenerator
    {
        $query = $this->createMock(Query::class);
        $query->method('getOneOrNullResult')->willReturn($queryResult);

        $expr = $this->createMock(Expr::class);
        $expr->method('like')->willReturn(new Expr\Comparison('p.receiptNumber', 'LIKE', "'$prefix%'"));

        $qb = $this->createMock(QueryBuilder::class);
        $qb->method('select')->willReturnSelf();
        $qb->method('where')->willReturnSelf();
        $qb->method('orderBy')->willReturnSelf();
        $qb->method('setMaxResults')->willReturnSelf();
        $qb->method('expr')->willReturn($expr);
        $qb->method('getQuery')->willReturn($query);

        $repo = $this->createMock(PaymentRepository::class);
        $repo->method('createQueryBuilder')->willReturn($qb);

        $systemSettingsManager = $this->createStub(\Ferienpass\CoreBundle\Settings\SystemSettingsManager::class);
        $systemSettingsManager->method('getReceiptNumberPrefix')->willReturn($prefix);

        return new ReceiptNumberGenerator($systemSettingsManager, $repo);
    }
}
