<?php

declare(strict_types=1);

namespace CpCreation\VitiCore\Tests\Command;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Command\PurgeExpiredRegistrationsCommand;
use CpCreation\VitiCore\User\ExpiredRegistrationPurger;
use Doctrine\DBAL\Connection;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Tester\CommandTester;

final class PurgeExpiredRegistrationsCommandTest extends TestCase
{
    public function testItCanPreviewThePurgeWithoutWritingPersonalDataToTheOutput(): void
    {
        $connection = $this->createMock(Connection::class);
        $connection
            ->expects(self::once())
            ->method('fetchOne')
            ->willReturn(12)
        ;
        $tester = new CommandTester(new PurgeExpiredRegistrationsCommand(
            new ExpiredRegistrationPurger($connection),
        ));

        $status = $tester->execute([
            '--dry-run' => true,
            '--batch-size' => '5',
            '--max-batches' => '2',
        ]);

        self::assertSame(Command::SUCCESS, $status);
        self::assertStringContainsString('Purge des inscriptions expirees', $tester->getDisplay());
        self::assertStringContainsString('Inscriptions eligibles', $tester->getDisplay());
        self::assertStringContainsString('12', $tester->getDisplay());
        self::assertStringContainsString("Aucune donnee n'a ete supprimee", $tester->getDisplay());
        self::assertStringNotContainsString('@', $tester->getDisplay());
    }

    public function testItRejectsAnInvalidBatchLimitBeforeQueryingTheDatabase(): void
    {
        $connection = $this->createMock(Connection::class);
        $connection
            ->expects(self::never())
            ->method('fetchOne')
        ;
        $connection
            ->expects(self::never())
            ->method('transactional')
        ;
        $tester = new CommandTester(new PurgeExpiredRegistrationsCommand(
            new ExpiredRegistrationPurger($connection),
        ));

        $status = $tester->execute(['--batch-size' => '0']);

        self::assertSame(Command::INVALID, $status);
        self::assertStringContainsString('compris entre 1 et', $tester->getDisplay());
    }

    public function testItRejectsLimitsThatCouldCreateAnUnboundedExecution(): void
    {
        foreach ([
            ['--batch-size' => '1001'],
            ['--max-batches' => '101'],
        ] as $options) {
            $connection = $this->createMock(Connection::class);
            $connection
                ->expects(self::never())
                ->method('fetchOne')
            ;
            $connection
                ->expects(self::never())
                ->method('transactional')
            ;
            $tester = new CommandTester(new PurgeExpiredRegistrationsCommand(
                new ExpiredRegistrationPurger($connection),
            ));

            self::assertSame(Command::INVALID, $tester->execute($options));
            self::assertStringContainsString('compris entre 1 et', $tester->getDisplay());
        }
    }
}
