<?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\NotificationHandler;

use Ferienpass\CoreBundle\Comment\ReplyTokenSigner;
use Ferienpass\CoreBundle\Entity\ConversationItem;
use Ferienpass\CoreBundle\Message\CommentPosted as CommentPostedMessage;
use Ferienpass\CoreBundle\Notification\CommentNotification;
use Ferienpass\CoreBundle\Notifier\Notifier;
use Ferienpass\CoreBundle\Repository\ConversationItemRepository;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Notifier\Recipient\Recipient;
use Symfony\Component\Uid\Uuid;

#[AsMessageHandler(bus: 'event.bus')]
class CommentPosted
{
    public function __construct(
        private readonly Notifier $notifier,
        private readonly ConversationItemRepository $comments,
        private readonly ReplyTokenSigner $tokenSigner,
    ) {
    }

    public function __invoke(CommentPostedMessage $message, Uuid $uuid): void
    {
        $comment = $this->comments->find(Uuid::fromString($message->getCommentUuid()));
        if (!$comment instanceof ConversationItem) {
            return;
        }

        $notification = $this->notifier->comment($comment);
        if (!$notification instanceof CommentNotification) {
            return;
        }

        $notification->recipient($message->getKind(), $message->getName(), $message->getReason());

        // Only admins and hosts hold an admin account, so only their mails carry
        // the /admin deep-links (subject page + notification settings). Parents
        // and other non-admin accounts get a link-free, reply-by-email message.
        if (\in_array($message->getKind(), ['admin', 'host'], true)) {
            if (null !== $message->getActionUrl()) {
                $notification->actionUrl($message->getActionUrl());
            }
            if (null !== $message->getSettingsUrl()) {
                $notification->settingsUrl($message->getSettingsUrl());
            }
        }

        // The signed applicant link goes to EVERY recipient: for a parent it is the
        // only link they can use at all, and for a colleague it is the thing they
        // are about to forward. It carries its own expiry (see AttendanceLinkGenerator).
        if (null !== $message->getAttendanceUrl()) {
            $notification->attendanceUrl($message->getAttendanceUrl());
        }

        // Route replies back to this comment via a tokenized reply-to address.
        if (null !== $replyAddress = $this->tokenSigner->replyAddress($comment)) {
            $notification->replyTo($replyAddress);
        }

        $this->notifier->send($notification->belongsTo($uuid), new Recipient($message->getEmail()));
    }
}
