<?php

/*
 * This file is part of the Serenity package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Serenity\AuthBundle\Tests\Authentication;

use PHPUnit\Framework\TestCase;
use Serenity\AuthBundle\Authentication\AuthenticationAdminFailureHandler;
use Serenity\CoreBundle\Notification\Command\NotificationCommand;
use Serenity\CoreBundle\Notification\Enum\PushLevel;
use Serenity\CoreBundle\Notification\Enum\PushTransport;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Contracts\Translation\TranslatorInterface;

final class AuthenticationAdminFailureHandlerTest extends TestCase
{
    public function testItStoresTheFailureAsAFlashBeforeRedirecting(): void
    {
        $messageBus = $this->createMock(MessageBusInterface::class);
        $router = $this->createMock(RouterInterface::class);
        $translator = $this->createMock(TranslatorInterface::class);

        $translator
            ->expects(self::once())
            ->method('trans')
            ->with('security.authentication.failure', [], 'serenity_auth_messages.admin')
            ->willReturn('Identifiants invalides');
        $router
            ->expects(self::once())
            ->method('generate')
            ->with('admin_login')
            ->willReturn('/dashboard/login');
        $messageBus
            ->expects(self::once())
            ->method('dispatch')
            ->with(self::callback(static function (object $message): bool {
                self::assertInstanceOf(NotificationCommand::class, $message);
                self::assertSame('Identifiants invalides', $message->message);
                self::assertSame(PushLevel::ERROR, $message->level);
                self::assertSame(PushTransport::FLASH, $message->transport);

                return true;
            }))
            ->willReturnCallback(static fn (object $message): Envelope => new Envelope($message));

        $handler = new AuthenticationAdminFailureHandler($messageBus, $router, $translator);
        $response = $handler->onAuthenticationFailure(Request::create('/dashboard/login'), new BadCredentialsException());

        self::assertInstanceOf(RedirectResponse::class, $response);
        self::assertSame(302, $response->getStatusCode());
        self::assertSame('/dashboard/login', $response->getTargetUrl());
    }
}
