<?php

declare(strict_types=1);

namespace App\Administration\Infrastructure\Messaging;

use App\Administration\Domain\Event\InvitationRenvoyee;
use App\Administration\Domain\Exception\UserNotFoundException;
use App\Administration\Domain\Model\ActivationToken\ActivationToken;
use App\Administration\Domain\Model\User\UserId;
use App\Administration\Domain\Repository\ActivationTokenRepository;
use App\Administration\Domain\Repository\UserRepository;
use App\Shared\Domain\Clock;
use App\Shared\Infrastructure\Tenant\TenantUrlBuilder;
use Psr\Log\LoggerInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Mime\Email;
use Twig\Environment;

/**
 * Sends a new invitation email when an invitation is resent.
 *
 * Creates a fresh activation token and emails the user with a new activation link.
 */
#[AsMessageHandler(bus: 'event.bus')]
final readonly class SendResendInvitationEmailHandler
{
    public function __construct(
        private MailerInterface $mailer,
        private Environment $twig,
        private ActivationTokenRepository $tokenRepository,
        private UserRepository $userRepository,
        private TenantUrlBuilder $tenantUrlBuilder,
        private Clock $clock,
        private LoggerInterface $logger,
        private string $fromEmail = 'noreply@classeo.fr',
    ) {
    }

    public function __invoke(InvitationRenvoyee $event): void
    {
        try {
            $user = $this->userRepository->get(UserId::fromString((string) $event->userId));
        } catch (UserNotFoundException $e) {
            $this->logger->warning('User no longer exists when processing resend invitation event, skipping.', [
                'userId' => (string) $event->userId,
                'email' => $event->email,
                'exception' => $e->getMessage(),
            ]);

            return;
        }

        $token = ActivationToken::generate(
            userId: (string) $event->userId,
            email: $event->email,
            tenantId: $event->tenantId,
            role: $user->role->value,
            schoolName: $user->schoolName,
            createdAt: $this->clock->now(),
        );

        $this->tokenRepository->save($token);

        $activationUrl = $this->tenantUrlBuilder->build($event->tenantId, '/activate/' . $token->tokenValue);

        $html = $this->twig->render('emails/invitation.html.twig', [
            'firstName' => $user->firstName,
            'lastName' => $user->lastName,
            'role' => $user->role->label(),
            'activationUrl' => $activationUrl,
        ]);

        $email = (new Email())
            ->from($this->fromEmail)
            ->to($event->email)
            ->subject('Rappel : Invitation à rejoindre Classeo')
            ->html($html);

        $this->mailer->send($email);
    }
}
