<?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\AdminBundle\Security;

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
 * Surfaces a failed login as a flash message instead of letting Symfony stash
 * the error in the session for the login template to render inline.
 *
 * This is what keeps the login page publicly cacheable: the page body no
 * longer contains per-user error text, so the same HTML is shared across every
 * visitor. The error rides out-of-band in the FOSHttpCacheBundle `flashes`
 * cookie (set on this redirect — which is itself private/uncacheable); the
 * `signin_login` Stimulus controller reads that cookie on the next page and
 * renders the message inline above the form. (It deliberately does NOT go
 * through the generic `flash_message` toast, which POSTs to
 * /admin/flash-message — an endpoint anonymous visitors can't reach.)
 */
final class AuthenticationFailureHandler implements AuthenticationFailureHandlerInterface
{
    public function __construct(
        private readonly UrlGeneratorInterface $urlGenerator,
        private readonly TranslatorInterface $translator,
    ) {
    }

    public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response
    {
        // Translate via the `security` domain, mirroring how the login
        // template used to render `error.messageKey|trans(.., 'security')`.
        $message = $this->translator->trans(
            $exception->getMessageKey(),
            $exception->getMessageData(),
            'security',
        );

        // Plain-string flash → the flash_message controller posts it as
        // `type=error&title=…`, which the admin Notification component renders
        // as a red toast (same shape as the controllers' addFlash('error', …)).
        $request->getSession()->getFlashBag()->add('error', $message);

        return new RedirectResponse($this->urlGenerator->generate('admin_login'));
    }
}
